??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲中文字幕无码永久在线,精品亚洲一区二区三区在线观看,亚洲Av熟妇高潮30phttp://m.tkk7.com/zellux/category/23657.htmlI'm awake but my world is half asleepzh-cnWed, 27 Jan 2010 13:00:00 GMTWed, 27 Jan 2010 13:00:00 GMT60Finding and Reproducing Heisenbugs in Concurrent Programshttp://m.tkk7.com/zellux/archive/2009/02/17/255048.htmlZelluXZelluXTue, 17 Feb 2009 03:30:00 GMThttp://m.tkk7.com/zellux/archive/2009/02/17/255048.htmlhttp://m.tkk7.com/zellux/comments/255048.htmlhttp://m.tkk7.com/zellux/archive/2009/02/17/255048.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/255048.htmlhttp://m.tkk7.com/zellux/services/trackbacks/255048.html今年的ASPLOS '09上zhou yuanyuan也有一关于如何concurrent program中发现隐藏的atomicity violation bugs的paperQ里面提C(jin)q篇paper

2008-11-30

OSDI '08上MSR发的paperQ针对ƈ发编E中难以发现的bug问题?/p>

paper的内容主要分两大块?/p>

一是如何在发现bug的时候记录下U程的运行先?thread interleaving)Q途径是在U程API和用L(fng)序多写一层wrapper functionsQ这里还有一些其他的问题Q比如只记录下了(jin)thread interleaving的话出现data race怎么解决{?/p>

另外一块内Ҏ(gu)如何遍历出给定程序运行后所能生的l果的集合,加入q个能实现的话那p把所有隐藏的bug都找出来?jin)。但是这个搜索空间很大,? 指数U的Q的一个结论就是:(x)l定一个程序有n个的U程Q所有线E共完成k条指令,那么cơ占先调度后U程的排列情冉|的复杂度?img src="http://10.132.140.73/wordpress/wp-content/cache/tex_d7c6a39b544e9306f24feffdc769cfc7.gif" class="tex" alt="k^{c}" align="absmiddle" />的,所以在实现遍历代码的时候必L效的降低k和c的倹{?/p>

ZelluX 2009-02-17 11:30 发表评论
]]>
Xen Notes [1]http://m.tkk7.com/zellux/archive/2008/10/17/235056.htmlZelluXZelluXFri, 17 Oct 2008 12:01:00 GMThttp://m.tkk7.com/zellux/archive/2008/10/17/235056.htmlhttp://m.tkk7.com/zellux/comments/235056.htmlhttp://m.tkk7.com/zellux/archive/2008/10/17/235056.html#Feedback5http://m.tkk7.com/zellux/comments/commentRss/235056.htmlhttp://m.tkk7.com/zellux/services/trackbacks/235056.htmlW一个testkernel在Xen中的载入

The Definitive Guide to Xen中第二章的例子,make成功后运行xen create domain_configQ报?br />Error: (2, ‘I(y)nvalid kernel? ‘xc_dom_compat_check: guest type xen-3.0-x86_32 not supported by xen kernel, sorry\n?

google之后发现是虚拟机cd讄的问题,q行xm info可以看到
xen_caps : xen-3.0-x86_32p
末尾的p表示Xen内核开启了(jin)PAE模式Q所以蝲入的kernel也必d启PAEQ在bootstrap.x86_32.S中加入PAE=yes选项卛_?br />
09?25, 2008
DomainU中调用do_console_io

The Definitive Guide to XenW二章的ExerciseQ通过调用hypercall page中的console_io输出Hello World?br />
void start_kernel(start_info_t * start_info)
{
    HYPERVISOR_console_io(CONSOLEIO_write,
12,"Hello World\n");
    
while(1);
}


但是默认选项~译和启动的Xen是不?x)保留DomainU中输出的信息。参考drivers/char/console.cQ可以看C要有两个选项控制?jin)DomainU的do_console_io输出Q?br />
#ifndef VERBOSE
    
/* Only domain 0 may access the emergency console. */
    
if ( current->domain->domain_id != 0 )
        
return -EPERM;
#endif

if ( opt_console_to_ring )
{
    
for ( kptr = kbuf; *kptr != '\0'; kptr++ )
        putchar_console_ring(
*kptr);
    send_guest_global_virq(dom0, VIRQ_CON_RING);
}


VERBOSE选项可以在编译Xen的时候开启debug选项Q而opt_console_to_ring则是一个启动选项Q在grub的启动选项中增加loglvl=all guest_loglvl=all console_to_ring卛_?br />
重启Xen后就能通过xm dmesg看到Hello World?jin)?br />
09?25, 2008
Xen: Remove support for non-PAE 32-bit

看来我还是用Xen 3.1?= =

Subject: [Xen-devel] [PATCH] xen: remove support for non-PAE 32-bitLink to this message
From: Jeremy Fitzhardinge (jer…@goop.org)
Date: 05/09/2008 04:05:34 AM
List: com.xensource.lists.xen-devel

Non-PAE operation has been deprecated in Xen for a while, and is rarely tested or used. xen-unstable has now officially dropped non-PAE support. Since Xen/pvops?non-PAE support has also been broken for a while, we may as well completely drop it altogether.

10?07, 2008
IA-32 Memory Virtualization
http://www.intel.com/technology/itj/2006/v10i3/3-xen/4-extending-with-intel-vt.htm
o_figure_3.gif
上图为full virtulization的情况,即不修改Guest OS的行为时的解x案。Xen为每个Guest OSl护?jin)一张shadow page tableQ其中映的地址为machine address。一U比较高效的Ҏ(gu)是设|Guest OS的page table为只读,当Guest OS试图修改q个虚拟表Ӟ发生page fault被Xen截获QXen修改shadow page table中相应的数据Q把pseudo-physical address转化成machine addressQ。另外一个优化是guest page table被修Ҏ(gu)不修改shadow page tableQ只是把它放C个待更新列表中,{Guest OS执行?jin)刷新tlb的指令后再一ơ性更新?br />
The Definitive Guide to Xen上还提到?jin)另一U基于full paravirtulization和shadow page table之间的方案。Xen把Guest OS的page table|ؓ(f)只读Q当Guest OS试图修改page tableӞXen捕获到page faultQ把page directory中对应的入口|ؓ(f)无效Q再把page tableҎ(gu)可写让Guest OS修改。由于page directory中对应的入口被设成无效了(jin)Q下ơ访问该地址时还是会(x)发生page faultQ这时候Xen再修改page directory和page table的对应项p?jin)?br />
q种Ҏ(gu)意味着Guest OS中内核管理模块直接和machine address打交道,而其他部分则仍然使用pseudo-physical address。另外这U情况下page directory不能被Guest OS修改?br />
另外Xenq用C(jin)D|Ӟ用来为Xen保留地址I间开始的64M内存?br />

ZelluX 2008-10-17 20:01 发表评论
]]>
几个q行计算、内核相关的链接http://m.tkk7.com/zellux/archive/2008/10/10/233603.htmlZelluXZelluXFri, 10 Oct 2008 07:29:00 GMThttp://m.tkk7.com/zellux/archive/2008/10/10/233603.htmlhttp://m.tkk7.com/zellux/comments/233603.htmlhttp://m.tkk7.com/zellux/archive/2008/10/10/233603.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/233603.htmlhttp://m.tkk7.com/zellux/services/trackbacks/233603.html依然是内|日志的汇?br />
1. sysenter的介l?br />http://www.codeguru.com/cpp/w-p/system/devicedriverdevelopment/article.php/c8223

System Call Optimization with the SYSENTER Instruction
by John Gulbrandsen
Windows下的

2. The SLUB allocator
slab的改q版?/p>

http://lwn.net/Articles/229984/

http://lwn.net/Articles/229096/

Christoph’s response is the SLUB allocator, a drop-in replacement for the slab code. SLUB promises better performance and scalability by dropping most of the queues and related overhead and simplifying the slab structure in general, while retaining the current slab allocator interface.

Wider use may be in the cards: the SLUB allocator is in the -mm tree now and could hit the mainline as soon as 2.6.22. The simplified code is attractive, as is the claimed 5-10% performance increase. If merged, SLUB is likely to coexist with the current slab allocator (and the SLOB allocator intended for small systems) for some time. In the longer term, the current slab code may be approaching the end of its life.

3. Compilers and More: Parallel Programming Made Easy?
http://www.hpcwire.com/features/Compilers_and_More_Parallel_Programming_Made_Easy.html

by Michael Wolfe, Compiler Engineer, The Portland Group, Inc.

4. OpenCL slides, SIGGRAPH '08
发信? jjgod (while(!asleep()) sheep++;), 信区: CSArch
标?? SIGGRAPH 08 上的 OpenCL slides
发信? 水木C֌ (Mon Sep 15 01:32:03 2008), 站内

?来源:·水木C֌ newsmth.net·[FROM: 125.33.176.*]

附g: munshi-opencl.pdf (1338 KB) 链接:
http://att.newsmth.net/att.php?p.272.35430.226.pdf
全文链接Q?a >http://www.newsmth.net/bbscon.php?bid=272&id=35430

5. linux-gate.so
http://www.trilithium.com/johan/2005/08/linux-gate/
linux下用sysenter的机?/p>

ZelluX 2008-10-10 15:29 发表评论
]]>
OS Lab 零散记录http://m.tkk7.com/zellux/archive/2008/10/10/233601.htmlZelluXZelluXFri, 10 Oct 2008 07:21:00 GMThttp://m.tkk7.com/zellux/archive/2008/10/10/233601.htmlhttp://m.tkk7.com/zellux/comments/233601.htmlhttp://m.tkk7.com/zellux/archive/2008/10/10/233601.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/233601.htmlhttp://m.tkk7.com/zellux/services/trackbacks/233601.html
Time : 2008-08-20 21:44
汇编文g中导出函数符?br />

Linux 2.4.18的linux/linkage.h文g定义?jin)若q相关的?br />

#define SYMBOL_NAME(X) X
#ifdef __STDC__
#define SYMBOL_NAME_LABEL(X) X##:
#else
#define SYMBOL_NAME_LABEL(X) X/**/:
#endif
 
#define __ALIGN .align 16,0x90
#define __ALIGN_STR ".align 16,0x90"
 
#define ALIGN __ALIGN
#define ALIGN_STR __ALIGN_STR
 
#define ENTRY(name) \
  .globl SYMBOL_NAME(name); \
  ALIGN; \
  SYMBOL_NAME_LABEL(name)

用ENTRY(name)p定义函数?jin)。后来发现Flux OSKit中本来就提供?jin)类似功能的宏,定义在inc/asm.h中?br />使用的时候需要再写一个c语言的wrapper functionQ至?.4.18里面是这么做的)(j)
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");

Time : 2008-08-22 15:56
OS Lab 4 debugging notes [1]
pȝ调用 fork()

用Simics跟踪一条条汇编分析表映射、寄存器D真是体力zd。?/p>

1. 实现Copy On WriteӞ如果某一个用h页面有多个q程׃nQ其中一个进E修改该面旉要创Z个新的页面。一开始偶忘了(jin)把原来页面的内容复制到新的页面了(jin) =_= 另外׃新的面要代替老的面Q或者说它们的物理地址不同Q但虚拟地址相同Q我的方法是在内核态开辟一个大ؓ(f)一个页面的I间作ؓ(f)中{?/p>

2. do_fork函数中,子进E复制父q程的页表的同时?x)把父进E页表项|ؓ(f)不可写,注意最后要flush tlb。因Z开始没有flush tlbQ导致最后用hforkq回以后d的信息来自于tlbQ直接改写了(jin)׃n面中fork的返回地址Q导致切换到子进E时fork的返回地址丢失。这个bug让我郁闷?jin)两三个时。?/p>

3. 使用两次forkӞW二ơforkq回的pid?x)被?gu)。查?jin)下发现为用L(fng)间分配物理页面的代码里居然在分配好以后没有把对应的struct|ؓ(f)已用,l果DW二个子q程COW创徏新页面时得到?jin)原来的父进E页面,改写?jin)父q程面内容?br />

Time : 2008-08-23 19:41
OS Lab4 debugging notes [2]
 
pȝ调用 exec()

1. 清空表的用L(fng)间映的函数一开始写得ytsQbug到处都是Q比如free的时候没使用指向内存块首地址的指针,记录内存地址的变量没有篏加?/p>

2. exec传递给内核态的两个参数必须先在内核态保存一个副本,否则清空用户态页表后无法得到这两个参数信息?jin)?/p>

3. 分配l用h的面必须先清Ӟ一斚w考虑到安全性,另一斚w不清零会(x)隐藏一些潜在的bug。一开始我没有在内核执行exec的时候完整的复制所有的参数Q而是直接指向?jin)原q程的内存空_(d)׃清空表后再ơ申h表时得C(jin)原来的页面,l果正好原来那个保存参数的页面和新进E的该页面重合了(jin) =_= 于是费?jin)不时间在q个bug?/p>

Time : 2008-08-31 1:18
OS Lab5 debugging notes

q算利Q不q这个lab蛮无聊的Q等有空?jin)把syscallҎ(gu)cMlinux的做法,单一中断?寄存器选择syscall?/p>

1. 最花时间的一个bug是lsq回值没有改成应用程序数Q结果一开始一直以为是brkpȝ调用没写好,最后才发现问题出在q么的地方?/p>

2. brk的逻辑q不是很清楚Q尽通过?jin)简单的试Q但是debug输出的信息显Cbrk增长的很快,l常是一个页一个页涨的Q看来还得查下brk的具体行为?/p>

3. 写了(jin)个比MAGIC_BREAK好用一点的宏,因ؓ(f)用户态的E序都是按二q制d的,Simics无法得到函数信息Q函数名、当前行数等Q,利用C99的宏写了(jin)个新的INFO_BREAK

#define I(yng)NFO_BREAK \
    
do {  \
        lprintf_kern(
"break in %s:%d", __FUNCTION__, __LINE__); \
        MAGIC_BREAK; \
    }
 while (0) \


ZelluX 2008-10-10 15:21 发表评论
]]>
OSLab之中断处?http://m.tkk7.com/zellux/archive/2008/09/02/226312.htmlZelluXZelluXTue, 02 Sep 2008 03:55:00 GMThttp://m.tkk7.com/zellux/archive/2008/09/02/226312.htmlhttp://m.tkk7.com/zellux/comments/226312.htmlhttp://m.tkk7.com/zellux/archive/2008/09/02/226312.html#Feedback5http://m.tkk7.com/zellux/comments/commentRss/226312.htmlhttp://m.tkk7.com/zellux/services/trackbacks/226312.htmlZellux (null), 信区: Software_06
? ? OSLab之中断处?br />发信? 日月光华 (2008q?8?0?0:15:58 星期?, 站内信g

1. 准备工作
在开始分析Support Code之前Q先配置下我们的Source InsightQ它能够支?s文g的搜索?br />
在Options->Document Options->Document Types中选择x86 Asm Source FileQ在File fileter中增加一?.sQ变?.asm;*.inc;*.s 然后在Project->Add and Remove
Project Files中重新将整个oslab的目录加入,q样以后q行文本搜烦(ch)?s文g也不?x)漏掉?jin)?br />
2. Source Insight使用
接下来简单分析下内核启动的过E,在浏览代码的q程中可以迅速的掌握Source Insight的用技巧?br />
lib/multiboot /multiboot.s完成?jin)初始化工作Q可以看到其中一句call
EXT(multiboot_main)调用?jin)C函数multiboot_mainQ用ctrl+/搜烦(ch)包含multiboot_main的所有文Ӟ最lbase_multiboot_main.c中找C(jin)它的定义。依ơ进行cpu、内存的?br />始化Q然后开启中断,跌{到kernel_main函数Q也是Lab1中所要改写的函数之一。另?br />在这里可以通过ctrl+单击或者ctrl+=跌{到相应的函数定义处,很方ѝ?br />
3. irq处理初始化工?br />来看下Lab 1的重点之一Qirq的处理。跟tmultiboot_main->base_cpu_setup->base_cp
u_init->base_irq_initQ可以看到这行代?br />gate_init(base_idt, base_irq_inittab, KERNEL_CS);
l箋使用ctrl+/扑ֈbase_irq_inittab的藏w之处:(x)base_irq_inittab.s

4. base_irq_inittab.s
q个汇编文g做了(jin)不少重复性工作,方便我们在c语言U别实现各种handler?br />GATE_INITTAB_BEGIN(base_irq_inittab) /* irq处理函数表的起始Q还记得jump
table 吗? */
MASTER(0, 0) /* irq0 对应的函?*/


来看看这个MASTER(0, 0)宏展开后是什么样子:(x)
#define MASTER(irq, num) \
GATE_ENTRY(BASE_IRQ_MASTER_BASE + (num), 0f, ACC_PL_K|ACC_INTR_GATE) ;\
P2ALIGN(TEXT_ALIGN) ;\
0: ;\
pushl $(irq) /* error code = irq vector */ ;\
pushl $BASE_IRQ_MASTER_BASE + (num) /* trap number */ ;\
pusha /* save general registers */ ;\
movl $(irq),%ecx /* irq vector number */ ;\
movb $1 << num,%dl /* pic mask for this irq */ ;\
jmp master_ints

依次push irqPtrapP0x20+irqP(j)Q通用寄存器(eax ecx{)(j)入栈Q把irq号保
存到ecx寄存器,然后跌{到master_intsQmaster_ints是所有master interrupts公用
的代码?br />
跌master_ints的前几行Q从W七行开?br /> /* Acknowledge the interrupt */
movb $0x20,%al
outb %al,$0x20

/* Save the rest of the standard trap frame (oskit/x86/base_trap.h). */
pushl %ds
pushl %es
pushl %fs
pushl %gs

/* Load the kernel's segment registers. */
movw %ss,%dx
movw %dx,%ds
movw %dx,%es

/* Increment the hardware interrupt nesting counter */
incb EXT(base_irq_nest)

/* Load the handler vector */
movl EXT(base_irq_handlers)(,%ecx,4),%esi

注释写得很详l,首先发?x20?x20端口Q也是Lab1文档上所说的发送INT_CTL_DON
E到INT_CTL_REGQ看来这一步support code已经替我们完成了(jin)。接下来保存四个D寄?br />器ds es fs gsQƈdkernel态的D寄存器信息?br />
最后一句很关键Q把base_irq_handlers + %ecx * 4q个g存到?jin)esi寄存器中Q?ecx
中保存了(jin)irqP?4则是一个函数指针的大小Q那么base_irq_handlers是什么呢Q
l用ctrl+/搜烦(ch)Q可以在base_irq.c中找到这个数l的定义
unsigned int (*base_irq_handlers[BASE_IRQ_COUNT])(struct trap_state *ts)
且初始时q个数组的每一w是base_irq_default_handler

看来q句汇编代码的功能是把处理irq对应的函数地址保存C(jin)esi寄存器中?br />Z(jin)证实q一点,l箋看base_irq_inittab.s的代码:(x)
#else
/* Call the interrupt handler with the trap frame as a parameter */
pushl %esp
call *%esi
popl %edx
#endif
果然Q在保存?jin)esp值后Q紧接着p用了(jin)esi指向的那个函数。而从那个函数q回后,
之前在栈上保存的相关信息都被恢复?jin)?x)

/* blah blah blah */
/* Return from the interrupt */
popl %gs
popl %fs
popl %es
popl %ds
popa
addl $4*2,%esp /* Pop trap number and error code */
iret
q样恢复到?jin)进入这个irq处理单元前的状态,文档中所要求的保存通用寄存器这一?br />其实在这里也已经完成?jin),不需要我们自己写代码?br />
好了(jin)Q这样一分析后,我们要做的事情就很简单,是把base_irq_handlers数组中的?br />应项Ҏ(gu)相应的handler函数p?jin)?br />注意index是相应的idt_entry号减去BASE_IRQ_SLAVE_BASEQ或者直接用IRQ受?

另外q个数组的初始值都是base_irq_default_handlerQ用ctrl+左键跛_q个函数的定
义,可以看到q个函数只有一句简单的输出语句Q?br /> printf("Unexpected interrupt %d\n", ts->err);
而这是没有注册handler前我们所看到的那句Unexpected interrupt 0的来源了(jin)?

5. struct trap_state *ts
所有的handler函数的参数都是一个struct trap_state *tsQ这个参数是哪来的呢Q?br />注意call *%esi的前一?br /> /* Call the interrupt handler with the trap frame as a parameter */
pushl %esp
q里把当前的esp当作指向ts的指针传l了(jin)handlerQ列一下从esp指向的地址开始的内容
Q也是在此之前push入栈的内容:(x)

pushl $(irq) /* error code = irq vector */ ;\
pushl $BASE_IRQ_MASTER_BASE + (num) /* trap number */ ;\
pusha /* save general registers */ ;\
pushl %ds
pushl %es
pushl %fs
pushl %gs

再看一下trap_state的定义,你会(x)发现正好和push的顺序相反:(x)
/* Saved segment registers */
unsigned int gs;
unsigned int fs;
unsigned int es;
unsigned int ds;

/* PUSHA register state frame */
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int cr2; /* we save cr2 over esp for page faults */
unsigned int ebx;
unsigned int edx;
unsigned int ecx;
unsigned int eax;

/* Processor trap number, 0-31. */
unsigned int trapno;

/* Error code pushed by the processor, 0 if none. */
unsigned int err;

而这个定义后面的
/* Processor state frame */
unsigned int eip;
unsigned int cs;
unsigned int eflags;
unsigned int esp;
unsigned int ss;
则是发生interrupt时硬件自动push的五个数据(参见Understand the Linux KernelQ?

也就是说Qts指针指向的是调用当前handler前的寄存器状态,也是当前handlerl束?br />用来恢复的寄存器状态,?jin)解q一点对以后的几个lab帮助很大?

p.s. 另外提一句和q个lab无关的话Q非vm86模式下栈上是不会(x)有v86_es{四个寄存器
信息的,所以以后根据task_struct指针计算*ts的地址时用的偏移量不应该是sizeof(
struct trap_state)

6. The End
q样差不多就把support code中处理interrupt的方法过?jin)一遍(另外q有base_trap_in
ittab.sQ不q和irq的处理很怼Q?br />
?jin)解q些后Lab1比较简单了(jin)Q不需要Q何内嵌汇~代码即可完成?br />

ZelluX 2008-09-02 11:55 发表评论
]]>
最q读的两paperhttp://m.tkk7.com/zellux/archive/2008/05/20/201737.htmlZelluXZelluXTue, 20 May 2008 12:18:00 GMThttp://m.tkk7.com/zellux/archive/2008/05/20/201737.htmlhttp://m.tkk7.com/zellux/comments/201737.htmlhttp://m.tkk7.com/zellux/archive/2008/05/20/201737.html#Feedback1http://m.tkk7.com/zellux/comments/commentRss/201737.htmlhttp://m.tkk7.com/zellux/services/trackbacks/201737.html阅读全文

ZelluX 2008-05-20 20:18 发表评论
]]>
Anti-CAPTCHAhttp://m.tkk7.com/zellux/archive/2008/04/18/193899.htmlZelluXZelluXThu, 17 Apr 2008 16:30:00 GMThttp://m.tkk7.com/zellux/archive/2008/04/18/193899.htmlhttp://m.tkk7.com/zellux/comments/193899.htmlhttp://m.tkk7.com/zellux/archive/2008/04/18/193899.html#Feedback1http://m.tkk7.com/zellux/comments/commentRss/193899.htmlhttp://m.tkk7.com/zellux/services/trackbacks/193899.html
Microsoft Live Mail  http://securitylabs.websense.com/content/Blogs/3063.aspx#
http://securitylabs.websense.com/content/Blogs/2907.aspx

Google http://securitylabs.websense.com/content/Blogs/2919.aspx#



ZelluX 2008-04-18 00:30 发表评论
]]>
LW记(6) - 虚拟存储http://m.tkk7.com/zellux/archive/2008/02/27/182436.htmlZelluXZelluXWed, 27 Feb 2008 15:29:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/27/182436.htmlhttp://m.tkk7.com/zellux/comments/182436.htmlhttp://m.tkk7.com/zellux/archive/2008/02/27/182436.html#Feedback4http://m.tkk7.com/zellux/comments/commentRss/182436.htmlhttp://m.tkk7.com/zellux/services/trackbacks/182436.html本来想看完pagefault的处理的Q不q实验室有事情了(jin)Q只能先把这一半放上来?jin)?/p>

面的分配与回收使用?jin)一个叫做buddy allocator的机Ӟkernelnewbies上的解释
The memory allocation scheme used in the kernel. A vector of lists of free pages is kept, ordered by the size of the chunk (in powers of two). When a chunk is allocated, it is removed from the relevant list. When a chunk is freed back to the free pages pool, it is placed in the relevant list, starting from the top. If it is physically contiguous with a present chunk, they are merged and placed in the list above (i.e. where the chunks are twice the size), and this operation percolates up the vector. As regions are merged whenever possible, this design helps to reduce memory fragmentation.

首先在zone_struct{} 中保存了(jin)一个free_area_t数组Q这个数l记录了(jin)各种大小的空闲内存块的信息?br />include/linux/mmzone.h:


free_area_struct {}

面分配Ӟ扑ֈ适合大小的free_area_struct{}Q然后从free_list中找有没有空闲的内存块,如果没有找更大的free_area_struct{}Q因为大都?^nQ很Ҏ(gu)把大块内存拆开Q一块分配给hQ剩下的保存到对应大的队列中?br />面回收时主要的问题是如何解册多的内存片。当面块被释放Ӟ先检查是否有相同大小的相?c)闲块存在Q如果有的话q合v来(递归q程Q?img src ="http://m.tkk7.com/zellux/aggbug/182436.html" width = "1" height = "1" />

ZelluX 2008-02-27 23:29 发表评论
]]>
Patching CVE-2008-0600, Local Root Exploithttp://m.tkk7.com/zellux/archive/2008/02/27/182572.htmlZelluXZelluXWed, 27 Feb 2008 15:15:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/27/182572.htmlhttp://m.tkk7.com/zellux/comments/182572.htmlhttp://m.tkk7.com/zellux/archive/2008/02/27/182572.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/182572.htmlhttp://m.tkk7.com/zellux/services/trackbacks/182572.html
http://kerneltrap.org/Linux/Patching_CVE-2008-0600_Local_Root_Exploit


ZelluX 2008-02-27 23:15 发表评论
]]>
[zz]LKM Rootkits on Linux x86 v2.6http://m.tkk7.com/zellux/archive/2008/02/26/182289.htmlZelluXZelluXTue, 26 Feb 2008 11:36:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/26/182289.htmlhttp://m.tkk7.com/zellux/comments/182289.htmlhttp://m.tkk7.com/zellux/archive/2008/02/26/182289.html#Feedback3http://m.tkk7.com/zellux/comments/commentRss/182289.htmlhttp://m.tkk7.com/zellux/services/trackbacks/182289.html阅读全文

ZelluX 2008-02-26 19:36 发表评论
]]>
信号量用例E?http://m.tkk7.com/zellux/archive/2008/02/21/181074.htmlZelluXZelluXThu, 21 Feb 2008 07:13:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/21/181074.htmlhttp://m.tkk7.com/zellux/comments/181074.htmlhttp://m.tkk7.com/zellux/archive/2008/02/21/181074.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/181074.htmlhttp://m.tkk7.com/zellux/services/trackbacks/181074.html/**//* semabinit.c ...  阅读全文

ZelluX 2008-02-21 15:13 发表评论
]]>
LW记(5) - ׃n内存http://m.tkk7.com/zellux/archive/2008/02/21/181046.htmlZelluXZelluXThu, 21 Feb 2008 06:10:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/21/181046.htmlhttp://m.tkk7.com/zellux/comments/181046.htmlhttp://m.tkk7.com/zellux/archive/2008/02/21/181046.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/181046.htmlhttp://m.tkk7.com/zellux/services/trackbacks/181046.html ...  阅读全文

ZelluX 2008-02-21 14:10 发表评论
]]>
Hacking the Kernel - 修改pȝ调用?/title><link>http://m.tkk7.com/zellux/archive/2008/02/19/180686.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Tue, 19 Feb 2008 06:55:00 GMT</pubDate><guid>http://m.tkk7.com/zellux/archive/2008/02/19/180686.html</guid><wfw:comment>http://m.tkk7.com/zellux/comments/180686.html</wfw:comment><comments>http://m.tkk7.com/zellux/archive/2008/02/19/180686.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/zellux/comments/commentRss/180686.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/zellux/services/trackbacks/180686.html</trackback:ping><description><![CDATA[昨天是没找到正的sys_call_table的地址Q原来我之前在虚拟机上装的ArchLinux?4位的。?br />今天在真Z成功C改了(jin)pȝ调用表?br />试环境QArchLinux 2.6.24<br /><br />1. 2.4.20以后的内核出于安全考虑Q没有导出sys_call_tableW号Q所以要先通过System.map扑ֈsys_call_table的地址<br /><u>$ cat /boot/System.map26 | grep sys_call_table</u><br />c0375680 R sys_call_table<br />另外也可以用nm工具获得vmlinux中的所有符?br /><u>$ nm /usr/src/linux-2.6.24-ARCH/vmlinux | grep sys_call_table</u><br />l果一?br /><br />2. 以添加一个把uidҎ(gu)root(0)ZQ写一个内核模块:(x)<br />addcall.c<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Code_Closed_Image_145101" onclick="this.style.display='none'; Code_Closed_Text_145101.style.display='none'; Code_Open_Image_145101.style.display='inline'; Code_Open_Text_145101.style.display='inline';" height="16" src="http://m.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" /><img id="Code_Open_Image_145101" style="DISPLAY: none" onclick="this.style.display='none'; Code_Open_Text_145101.style.display='none'; Code_Closed_Image_145101.style.display='inline'; Code_Closed_Text_145101.style.display='inline';" height="16" src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span id="Code_Closed_Text_145101" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"></span><span id="Code_Open_Text_145101" style="DISPLAY: none"><br /><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">linux</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">kernel.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">linux</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">module.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">linux</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">init.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">linux</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">unistd.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">linux</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">time.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">asm</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">uaccess.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">linux</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">sched.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000"> __NR_changeuid 238</span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />MODULE_DESCRIPTION(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Change uid to 0</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />MODULE_AUTHOR(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ZelluX</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">saved) (</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">**</span><span style="COLOR: #000000"> sys_call_table </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0xc0375680</span><span style="COLOR: #000000">;<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />asmlinkage </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> sys_changeuid(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_372_507_Open_Image" onclick="this.style.display='none'; Codehighlighter1_372_507_Open_Text.style.display='none'; Codehighlighter1_372_507_Closed_Image.style.display='inline'; Codehighlighter1_372_507_Closed_Text.style.display='inline';" src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_372_507_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_372_507_Closed_Text.style.display='none'; Codehighlighter1_372_507_Open_Image.style.display='inline'; Codehighlighter1_372_507_Open_Text.style.display='inline';" src="http://m.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_372_507_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://m.tkk7.com/images/dot.gif" /></span><span id="Codehighlighter1_372_507_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    current</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">uid </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> current</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">euid </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> current</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">suid </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> current</span><span style="COLOR: #000000">-></span><span style="COLOR: #000000">fsuid </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    printk(KERN_ALERT </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">uid has been changed.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br /><img src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> __init init_addsyscall(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_543_741_Open_Image" onclick="this.style.display='none'; Codehighlighter1_543_741_Open_Text.style.display='none'; Codehighlighter1_543_741_Closed_Image.style.display='inline'; Codehighlighter1_543_741_Closed_Text.style.display='inline';" src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_543_741_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_543_741_Closed_Text.style.display='none'; Codehighlighter1_543_741_Open_Image.style.display='inline'; Codehighlighter1_543_741_Open_Text.style.display='inline';" src="http://m.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_543_741_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://m.tkk7.com/images/dot.gif" /></span><span id="Codehighlighter1_543_741_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    saved </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">) (</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)) (sys_call_table[__NR_changeuid]);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    sys_call_table[__NR_changeuid] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (unsigned </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">) sys_changeuid;<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    printk(KERN_ALERT </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">the call has been added.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br /><img src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> __exit exit_addsyscall(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br /><img id="Codehighlighter1_778_892_Open_Image" onclick="this.style.display='none'; Codehighlighter1_778_892_Open_Text.style.display='none'; Codehighlighter1_778_892_Closed_Image.style.display='inline'; Codehighlighter1_778_892_Closed_Text.style.display='inline';" src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_778_892_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_778_892_Closed_Text.style.display='none'; Codehighlighter1_778_892_Open_Image.style.display='inline'; Codehighlighter1_778_892_Open_Text.style.display='inline';" src="http://m.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_778_892_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://m.tkk7.com/images/dot.gif" /></span><span id="Codehighlighter1_778_892_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    sys_call_table[__NR_changeuid] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (unsigned </span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">) saved;<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    printk(KERN_ALERT </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">the call has been removed</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />module_init(init_addsyscall);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />module_exit(exit_addsyscall);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span></span></div><br />对应的MakefileQ?br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Code_Closed_Image_145203" onclick="this.style.display='none'; Code_Closed_Text_145203.style.display='none'; Code_Open_Image_145203.style.display='inline'; Code_Open_Text_145203.style.display='inline';" height="16" src="http://m.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" /><img id="Code_Open_Image_145203" style="DISPLAY: none" onclick="this.style.display='none'; Code_Open_Text_145203.style.display='none'; Code_Closed_Image_145203.style.display='inline'; Code_Closed_Text_145203.style.display='inline';" height="16" src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span id="Code_Closed_Text_145203" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"></span><span id="Code_Open_Text_145203" style="DISPLAY: none"><br /><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">ifneq ($(KERNELRELEASE)</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">)<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />    obj-m :</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> addcall.o<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />else<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />    KERNELDIR ?</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> /lib/modules/$(shell uname -r)/build<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />    PWD  :</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> $(shell pwd)<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />default:<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />        $(MAKE) -C $(KERNELDIR) M</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">$(PWD) modules<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />endif<br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span></span></div><br />3. 使用insmod addcall.ko载入模块后,用dmesg可以看到the call has been added.<br />4. 试E序<br />test.c<br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id="Code_Closed_Image_145325" onclick="this.style.display='none'; Code_Closed_Text_145325.style.display='none'; Code_Open_Image_145325.style.display='inline'; Code_Open_Text_145325.style.display='inline';" height="16" src="http://m.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" /><img id="Code_Open_Image_145325" style="DISPLAY: none" onclick="this.style.display='none'; Code_Open_Text_145325.style.display='none'; Code_Closed_Image_145325.style.display='inline'; Code_Closed_Text_145325.style.display='inline';" height="16" src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span id="Code_Closed_Text_145325" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"></span><span id="Code_Open_Text_145325" style="DISPLAY: none"><br /><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">linux</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">unistd.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" />#include </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">></span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000"> __NR_changeuid 238</span><span style="COLOR: #000000"><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://m.tkk7.com/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> main()<br /><img id="Codehighlighter1_85_245_Open_Image" onclick="this.style.display='none'; Codehighlighter1_85_245_Open_Text.style.display='none'; Codehighlighter1_85_245_Closed_Image.style.display='inline'; Codehighlighter1_85_245_Closed_Text.style.display='inline';" src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_85_245_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_85_245_Closed_Text.style.display='none'; Codehighlighter1_85_245_Open_Image.style.display='inline'; Codehighlighter1_85_245_Open_Text.style.display='inline';" src="http://m.tkk7.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_85_245_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://m.tkk7.com/images/dot.gif" /></span><span id="Codehighlighter1_85_245_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Previous uid = %d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, syscall(__NR_getuid));<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    syscall(__NR_changeuid);<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Current uid = %d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, syscall(__NR_getuid));<br /><img src="http://m.tkk7.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br /><img src="http://m.tkk7.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: #000000"><br /></span></span></div><br />使用gcc -o test test.c~译<br /><br />5. q行./testQ即可看到类似的成功信息Q?br />Previous uid = 1002<br />Current uid = 0<br /><br />6. 卸蝲模块rmmod addcallQ此时再ơ运?/test׃(x)p|<img src ="http://m.tkk7.com/zellux/aggbug/180686.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/zellux/" target="_blank">ZelluX</a> 2008-02-19 14:55 <a href="http://m.tkk7.com/zellux/archive/2008/02/19/180686.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LW记(4) - ׃n内存http://m.tkk7.com/zellux/archive/2008/02/19/180612.htmlZelluXZelluXTue, 19 Feb 2008 03:30:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/19/180612.htmlhttp://m.tkk7.com/zellux/comments/180612.htmlhttp://m.tkk7.com/zellux/archive/2008/02/19/180612.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/180612.htmlhttp://m.tkk7.com/zellux/services/trackbacks/180612.html
主要的APIQ?br />shmget 创徏一块共享内?br />shmat 一块已l存在的׃n内存映射C个进E的地址I间
shmdt 取消一个进E的地址I间中的一块共享块的映?br />shmctl 理׃n内存Q和ioctl的风格很?br />
每一个新创徏的共享都׃个shmid_ds{}表示。struct shmid_ds在linux/shm.h中的定义Q?br />

其中存放权限信息的ipc_perm{}的定义ؓ(f)Q?br />include/linux/ipc.h

mode׃n的内存的d权限Q和chmod的参数有点像。mode低九(ji)位定义了(jin)讉K许可Q解释如下:(x)
0400 用户可读  0200用户可写  0040 l成员可读?0020 l成员可写?0004 其他用户可读  0002 其他用户可写
没有执行?0100 0010 ?0001

 



ZelluX 2008-02-19 11:30 发表评论
]]>
LW记(3) - pȝ调用http://m.tkk7.com/zellux/archive/2008/02/18/180462.htmlZelluXZelluXMon, 18 Feb 2008 06:35:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/18/180462.htmlhttp://m.tkk7.com/zellux/comments/180462.htmlhttp://m.tkk7.com/zellux/archive/2008/02/18/180462.html#Feedback4http://m.tkk7.com/zellux/comments/commentRss/180462.htmlhttp://m.tkk7.com/zellux/services/trackbacks/180462.html_syscall 宏:(x)
最单的没有参数的系l调用的实现Q?br />
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
#define _syscall0(type,name) \
type name(
void) \
{ \
long __res; \
__asm__ 
volatile ("int $0x80" \
    : 
"=a" (__res) \
    : 
"0" (__NR_##name)); \
__syscall_return(type,__res); \
}

以getuid()ZQ_syscall0(int, getuid)展开后就变成
int getuid(void)
{
    
long __res;
    __asm__ 
volatile("int $0x80"
                    :
"=a" (__res)
                    :
"0"  (__NR_getuid));
    __syscall_return(
int, __res);
}

E序把系l调用号__NR_getuid攑օeax寄存器,然后调用软中断?br />include/asm-i386/hw_irq.h中的定义Q?br />00025   #define SYSCALL_VECTOR  0x80;

arch/i386/kernel/traps.c中把该中断号l定到system_call函数Q?br />00944   set_system_gate(SYSCALL_VECTOR,&system_call);

system_call函数在arch/i386/kernel/entry.S中:(x)
ENTRY(system_call)
    pushl %eax            # save orig_eax
    SAVE_ALL
    GET_CURRENT(%ebx)
    testb $0x02
,tsk_ptrace(%ebx)    # PT_TRACESYS
    jne tracesys
    cmpl $(NR_syscalls)
,%eax
    jae badsys
    call *SYMBOL_NAME(sys_call_table)(
,%eax,4)
    movl %eax
,EAX(%esp)        # save the return value
ENTRY(ret_from_sys_call)
    cli                # need_resched and signals atomic test
    cmpl $
0,need_resched(%ebx)
    jne reschedule
    cmpl $
0,sigpending(%ebx)
    jne signal_return
restore_all:
    RESTORE_ALL
主要步骤Q?br />1. 保留一份系l调用号的最初拷?br />2. 保存堆栈环境(SAVE_ALL)
3. 得到当前task_struct的地址Q保存到ebx?br />4. (g)查系l调用号
5. Ҏ(gu)%eax调用可地址Q调用相应函?br />6. 在entry.S后面可以看到Q?br />
.data
ENTRY(sys_call_table)
    .long SYMBOL_NAME(sys_ni_syscall)    /* 
0  -  old "setup()" system call*/
        
    .long SYMBOL_NAME(sys_getuid16)
    .long SYMBOL_NAME(sys_stime)        /* 
25 */
    .long SYMBOL_NAME(sys_ptrace)
        
sys_call_table + %eax * 4是sys_getuid16地址Qkernel/uid16.c中:(x)
asmlinkage long sys_getuid16(void)
{
    
return high2lowuid(current->uid);
}
很简单的处理代码Q返回当前进E的uid。这里asmlinkage修饰W表C函数必M堆栈中,而不是从寄存器中拿参敎ͼ防止gcc用寄存器传参优化Q?br />7. 保存q回值eax到堆栈中的eax
8. RESTORE_ALL

另外q里再提一下GET_CURRENT的实?br />
#define GET_CURRENT(reg) \
    movl $-
8192, reg; \
    andl %esp, reg
很y妙的实现Q把栈指针与掩码-8192做与操作Q末?3位清Ӟ是当前的进E的task_struct地址?jin)?br />

接下来是利用内核模块动态添加一个系l调用的例程Q由?.4.20以后sys_call_tableW号不再被导Z(jin)Q要获得q个地址得手动hack。尚未成功,下次回过头来看看?img src ="http://m.tkk7.com/zellux/aggbug/180462.html" width = "1" height = "1" />

ZelluX 2008-02-18 14:35 发表评论
]]>
LW记(2) - 内核模块http://m.tkk7.com/zellux/archive/2008/02/10/179568.htmlZelluXZelluXSun, 10 Feb 2008 10:53:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/10/179568.htmlhttp://m.tkk7.com/zellux/comments/179568.htmlhttp://m.tkk7.com/zellux/archive/2008/02/10/179568.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/179568.htmlhttp://m.tkk7.com/zellux/services/trackbacks/179568.html阅读全文

ZelluX 2008-02-10 18:53 发表评论
]]>
Linux2.6内核驱动?.4的区?-Linux2.6内核驱动UL参考[zz]http://m.tkk7.com/zellux/archive/2008/02/10/179561.htmlZelluXZelluXSun, 10 Feb 2008 09:00:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/10/179561.htmlhttp://m.tkk7.com/zellux/comments/179561.htmlhttp://m.tkk7.com/zellux/archive/2008/02/10/179561.html#Feedback1http://m.tkk7.com/zellux/comments/commentRss/179561.htmlhttp://m.tkk7.com/zellux/services/trackbacks/179561.html 

作者:(x)晏渭?
随着Linux2.6的发布,׃2.6内核做了(jin)新的改动Q各个设备的驱动E序在不同程度上要进行改写。ؓ(f)?jin)方便各位Linux爱好者我把自己整理的q分 文档share出来。该文当列D?.6内核同以前版本的l大多数变化Q可惜的是由于时间和_֊有限没有详细列出各个函数的用法?/p>

1?使用新的入口
必须包含 <linux/init.h>
module_init(your_init_func);
module_exit(your_exit_func);
老版本:(x)int init_module(void);
void cleanup_module(voi);
2.4中两U都可以用,对如后面的入口函C必要昄包含M头文件?/p>

2?GPL
MODULE_LICENSE("Dual BSD/GPL");
老版本:(x)MODULE_LICENSE("GPL");

3?模块参数
必须昑ּ包含<linux/moduleparam.h>
module_param(name, type, perm);
module_param_named(name, value, type, perm);
参数定义
module_param_string(name, string, len, perm);
module_param_array(name, type, num, perm);
老版本:(x)MODULE_PARM(variable,type);
MODULE_PARM_DESC(variable,type);

4?模块别名
MODULE_ALIAS("alias-name");
q是新增的,在老版本中需?etc/modules.conf配置Q现在在代码中就可以实现?/p>

5?模块计数
int try_module_get(&module);
module_put();
老版本:(x)MOD_INC_USE_COUNT ?MOD_DEC_USE_COUNT

http://www.fsl.cs.sunysb.edu/~sean/parser.cgi?modules

In 2.4 modules, the MOD_INC_USE_COUNT macro is used to prevent unloading of the module while there is an open file. The 2.6 kernel, however, knows not to unload a module that owns a character device that's currently open.
However, this requires that the module be explicit in specifying ownership of character devices, using the THIS_MODULE macro.

You also have to take out all calls to MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT.
       
    static struct file_operations fops =
{
         .owner = THIS_MODULE,
         .read = device_read,
         .write = device_write,
         .open = device_open,
         .release = device_release
}    
       

The 2.6 kernel considers modules that use the deprecated facility to be unsafe, and does not permit their unloading, even with rmmod -f.

2.6,2.5的kbuild不需要到处加上MOD_INC_USE_COUNT来消除模块卸载竞争(module unload raceQ?/p>

6?W号导出
只有昄的导出符h能被其他模块使用Q默认不导出所有的W号Q不必用EXPORT_NO_SYMBOLS
老板本:(x)默认导出所有的W号Q除非用EXPORT_NO_SYMBOLS

7?内核版本(g)?
需要在多个文g中包?lt;linux/module.h>Ӟ不必定义__NO_VERSION__
老版本:(x)在多个文件中包含<linux/module.h>Ӟ除在L件外的其他文件中必须定义__NO_VERSION__Q防止版本重复定义?/p>

8?讑֤?
kdev_t被废除不可用Q新的dev_t拓展C(jin)32位,12位主讑֤P20位次讑֤受?
unsigned int iminor(struct inode *inode);
unsigned int imajor(struct inode *inode);
老版本:(x)8位主讑֤P8位次讑֤?
int MAJOR(kdev_t dev);
int MINOR(kdev_t dev);

9?内存分配头文件变?
所有的内存分配函数包含在头文g<linux/slab.h>Q而原来的<linux/malloc.h>不存?
老版本:(x)内存分配函数包含在头文g<linux/malloc.h>

10?l构体的初试?
gcc开始采用ANSI C的structl构体的初始化Ş式:(x)
static struct some_structure = {
.field1 = value,
.field2 = value,
..
};
老版本:(x)非标准的初试化Ş?
static struct some_structure = {
field1: value,
field2: value,
..
};

11?用户模式帮助?
int call_usermodehelper(char *path, char **argv, char **envp, int wait);
新增wait参数

12?request_module()
request_module("foo-device-%d", number);
老版本:(x)
char module_name[32];
printf(module_name, "foo-device-%d", number);
request_module(module_name);

13?dev_t引发的字W设备的变化
1、取L讑֤号ؓ(f)
unsigned iminor(struct inode *inode);
unsigned imajor(struct inode *inode);
2、老的register_chrdev()用法没变Q保持向后兼容,但不能访问设备号大于256的设备?
3、新的接口ؓ(f)
a)注册字符讑֤范围
int register_chrdev_region(dev_t from, unsigned count, char *name);
b)动态申请主讑֤?
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, char *name);
看了(jin)q两个函数郁闷吧^_^Q怎么和file_operationsl构联系h啊?别急!
c)包含 <linux/cdev.h>Q利用struct cdev和file_operationsq接
struct cdev *cdev_alloc(void);
void cdev_init(struct cdev *cdev, struct file_operations *fops);
int cdev_add(struct cdev *cdev, dev_t dev, unsigned count);
Q分别ؓ(f)Q申请cdevl构Q和fopsq接Q将讑֤加入到系l中Q好复杂啊!Q?
d)void cdev_del(struct cdev *cdev);
只有在cdev_add执行成功才可q行?
e)辅助函数
kobject_put(&cdev->kobj);
struct kobject *cdev_get(struct cdev *cdev);
void cdev_put(struct cdev *cdev);
q一部分变化和新增的/sys/dev有一定的兌?/p>

14?新增?proc的访问操?
<linux/seq_file.h>
以前?proc中只能得到string, seq_file操作能得到如long{多U数据?
相关函数Q?
static struct seq_operations 必须实现q个cMfile_operations得数据中得各个成员函数?
seq_printf()Q?
int seq_putc(struct seq_file *m, char c);
int seq_puts(struct seq_file *m, const char *s);
int seq_escape(struct seq_file *m, const char *s, const char *esc);
int seq_path(struct seq_file *m, struct vfsmount *mnt,
struct dentry *dentry, char *esc);
seq_open(file, &ct_seq_ops);
{等

15?底层内存分配
1?lt;linux/malloc.h>头文件改?lt;linux/slab.h>
2、分配标志GFP_BUFFER被取消,取而代之的是GFP_NOIO ?GFP_NOFS
3、新增__GFP_REPEATQ__GFP_NOFAILQ__GFP_NORETRY分配标志
4、页面分配函数alloc_pages()Qget_free_page()被包含在<linux/gfp.h>?
5、对NUMApȝ新增?jin)几个函敎ͼ?x)
a) struct page *alloc_pages_node(int node_id, unsigned int gfp_mask, unsigned int order);
b) void free_hot_page(struct page *page);
c) void free_cold_page(struct page *page);
6?新增Memory pools
<linux/mempool.h>
mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, void *pool_data);
void *mempool_alloc(mempool_t *pool, int gfp_mask);
void mempool_free(void *element, mempool_t *pool);
int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask);

16?per-CPU变量
get_cpu_var();
put_cpu_var();
void *alloc_percpu(type);
void free_percpu(const void *);
per_cpu_ptr(void *ptr, int cpu)
get_cpu_ptr(ptr)
put_cpu_ptr(ptr)
老版本?
DEFINE_PER_CPU(type, name);
EXPORT_PER_CPU_SYMBOL(name);
EXPORT_PER_CPU_SYMBOL_GPL(name);
DECLARE_PER_CPU(type, name);
DEFINE_PER_CPU(int, mypcint);
2.6内核采用?jin)可剥夺得调度方式这些宏都不安全?/p>

17?内核旉变化
1、现在的各个q_的HZ?
Alpha: 1024/1200; ARM: 100/128/200/1000; CRIS: 100; i386: 1000; IA-64: 1024; M68K: 100; M68K-nommu: 50-1000; MIPS: 100/128/1000; MIPS64: 100; PA-RISC: 100/1000; PowerPC32: 100; PowerPC64: 1000; S/390: 100; SPARC32: 100; SPARC64: 100; SuperH: 100/1000; UML: 100; v850: 24-100; x86-64: 1000.
2、由于HZ的变化,原来的jiffies计数器很快就溢出?jin),引入了(jin)新的计数器jiffies_64
3?include <linux/jiffies.h>
u64 my_time = get_jiffies_64();
4、新的时间结构增加了(jin)U秒成员变量
struct timespec current_kernel_time(void);
5、他的timer函数没变Q新?
void add_timer_on(struct timer_list *timer, int cpu);
6、新增纳U延时函数
ndelay()Q?
7、POSIX clocks 参考kernel/posix-timers.c

18?工作队列QworkqueueQ?
1、Q务队列(task queue Q接口函数都被取消,新增?jin)workqueue接口函数
struct workqueue_struct *create_workqueue(const char *name);
DECLARE_WORK(name, void (*function)(void *), void *data);
INIT_WORK(struct work_struct *work,
void (*function)(void *), void *data);
PREPARE_WORK(struct work_struct *work,
void (*function)(void *), void *data);
2、申明struct work_structl构
int queue_work(struct workqueue_struct *queue, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue, struct work_struct *work,
unsigned long delay);
int cancel_delayed_work(struct work_struct *work);
void flush_workqueue(struct workqueue_struct *queue);
void destroy_workqueue(struct workqueue_struct *queue);
int schedule_work(struct work_struct *work);
int schedule_delayed_work(struct work_struct *work, unsigned long delay);

19?新增创徏VFS?libfs"
libfsl创Z个新的文件系l提供了(jin)大量的API.
主要是对struct file_system_type的实现?
参考源代码Q?
drivers/hotplug/pci_hotplug_core.c
drivers/usb/core/inode.c
drivers/oprofile/oprofilefs.c
fs/ramfs/inode.c
fs/nfsd/nfsctl.c (simple_fill_super() example)

20?DMA的变?
未变化的有:(x)
void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_handle);
void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle);
变化的有Q?
1?void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);
void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle);
2、列举了(jin)映射方向Q?
enum dma_data_direction {
DMA_BIDIRECTIONAL = 0,
DMA_TO_DEVICE = 1,
DMA_FROM_DEVICE = 2,
DMA_NONE = 3,
};
3、单映射
dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, enum dma_data_direction direction);
void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction);
4、页面映?
dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction);
void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction);
5、有关scatter/gather的函敎ͼ(x)
int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction);
void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, enum dma_data_direction direction);
6、非一致性映(Noncoherent DMA mappingsQ?
void *dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);
void dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, unsigned long offset, size_t size,
enum dma_data_direction direction);
void dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle);
7、DAC (double address cycle)
int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
void pci_dac_dma_sync_single(struct pci_dev *dev, dma64_addr_t dma_addr, size_t len, int direction);

21?互斥
新增seqlock主要用于Q?
1、少量的数据保护
2、数据比较简?没有指针)Qƈ且用频率很?
3、对不生Q何副作用的数据的讉K
4、访问时写者不被饿?
<linux/seqlock.h>
初始?
seqlock_t lock1 = SEQLOCK_UNLOCKED;
或seqlock_t lock2; seqlock_init(&lock2);
void write_seqlock(seqlock_t *sl);
void write_sequnlock(seqlock_t *sl);
int write_tryseqlock(seqlock_t *sl);
void write_seqlock_irqsave(seqlock_t *sl, long flags);
void write_sequnlock_irqrestore(seqlock_t *sl, long flags);
void write_seqlock_irq(seqlock_t *sl);
void write_sequnlock_irq(seqlock_t *sl);
void write_seqlock_bh(seqlock_t *sl);
void write_sequnlock_bh(seqlock_t *sl);
unsigned int read_seqbegin(seqlock_t *sl);
int read_seqretry(seqlock_t *sl, unsigned int iv);
unsigned int read_seqbegin_irqsave(seqlock_t *sl, long flags);
int read_seqretry_irqrestore(seqlock_t *sl, unsigned int iv, long flags);

22?内核可剥?
<linux/preempt.h>
preempt_disable()Q?
preempt_enable_no_resched()Q?
preempt_enable_noresched()Q?
preempt_check_resched()Q?/p>

23?眠和唤醒
1、原来的函数可用Q新增下列函敎ͼ(x)
prepare_to_wait_exclusive()Q?
prepare_to_wait()Q?
2、等待队列的变化
typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int sync);
void init_waitqueue_func_entry(wait_queue_t *queue, wait_queue_func_t func);

24?新增完成事gQcompletion eventsQ?
<linux/completion.h>
init_completion(&my_comp);
void wait_for_completion(struct completion *comp);
void complete(struct completion *comp);
void complete_all(struct completion *comp);

25?RCUQRead-copy-updateQ?
rcu_read_lock();
void call_rcu(struct rcu_head *head, void (*func)(void *arg),
void *arg);

26?中断处理
1、中断处理有q回g(jin)?
IRQ_RETVAL(handled)Q?
2、cli(), sti(), save_flags(), ?restore_flags()不再有效Q应该用local_save
_flags() 或local_irq_disable()?
3、synchronize_irq()函数有改?
4、新增int can_request_irq(unsigned int irq, unsigned long flags);
5?request_irq() 和free_irq() ?<linux/sched.h>改到?<linux/interrupt.h>

27?异步I/O(AIO)
<linux/aio.h>
ssize_t (*aio_read) (struct kiocb *iocb, char __user *buffer, size_t count, loff_t pos);
ssize_t (*aio_write) (struct kiocb *iocb, const char __user *buffer, size_t count, loff_t pos);
int (*aio_fsync) (struct kiocb *, int datasync);
新增C(jin)file_operationl构中?
is_sync_kiocb(struct kiocb *iocb)Q?
int aio_complete(struct kiocb *iocb, long res, long res2);

28?|络驱动
1、struct net_device *alloc_netdev(int sizeof_priv, const char *name, void (*setup)(struct net_device *));
struct net_device *alloc_etherdev(int sizeof_priv);
2、新增NAPI(New API)
void netif_rx_schedule(struct net_device *dev);
void netif_rx_complete(struct net_device *dev);
int netif_rx_ni(struct sk_buff *skb);
(老版本ؓ(f)netif_rx())

29?USB驱动
老版本struct usb_driver取消?jin),新的l构体ؓ(f)
struct usb_class_driver {
char *name;
struct file_operations *fops;
mode_t mode;
int minor_base;
};
int usb_submit_urb(struct urb *urb, int mem_flags);
int (*probe) (struct usb_interface *intf,
const struct usb_device_id *id);

30?block I/O ?
q一部分做的改动最大。不叙?/p>

31?mmap()
int remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
struct page *(*nopage)(struct vm_area_struct *area, unsigned long address, int *type);
int (*populate)(struct vm_area_struct *area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot);
struct page *vmalloc_to_page(void *address);

32?零拷贝块I/O(Zero-copy block I/O)
struct bio *bio_map_user(struct block_device *bdev, unsigned long uaddr, unsigned int len, int write_to_vm);
void bio_unmap_user(struct bio *bio, int write_to_vm);
int get_user_pages(struct task_struct *task, struct mm_struct *mm, unsigned long start, int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);

33?高端内存操作kmaps
void *kmap_atomic(struct page *page, enum km_type type);
void kunmap_atomic(void *address, enum km_type type);
struct page *kmap_atomic_to_page(void *address);
老版本:(x)kmap() ?kunmap()?/p>

34?驱动模型
主要用于讑֤理?
1?sysfs
2?Kobjects

推荐文章Q?
http:/www-900.ibm.com/developerWorks/cn/linux/kernel/l-kernel26/index.shtml
http:/www-900.ibm.com/developerWorks/cn/linux/l-inside/index.shtml

2.6里不需要再定义“__KERNEL__”?#8220;MODULE”?jin)?
用下面的Makefile文g~译Q?/p>

代码:

    obj-m   := hello.o

    KDIR   := /lib/modules/$(shell uname -r)/build
    PWD      := $(shell pwd)
    default:
              $(MAKE) -C $(KDIR) M=$(PWD) modules



ZelluX 2008-02-10 17:00 发表评论
]]>
多文件内核模块的~译http://m.tkk7.com/zellux/archive/2008/02/10/179542.htmlZelluXZelluXSun, 10 Feb 2008 04:34:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/10/179542.htmlhttp://m.tkk7.com/zellux/comments/179542.htmlhttp://m.tkk7.com/zellux/archive/2008/02/10/179542.html#Feedback1http://m.tkk7.com/zellux/comments/commentRss/179542.htmlhttp://m.tkk7.com/zellux/services/trackbacks/179542.html 2.6内核~译pȝ提供?jin)一U不同的写法?br /> q里obj-m是树(wi)根,hello-objs是hello的两个结炏V?br />
ifneq ($(KERNELRELEASE),)
        obj-m :
= hello.o
        hello-objs :
= start.o stop.o
else
        KERNELDIR ?
= /lib/modules/$(shell uname -r)/build
        PWD  :
= $(shell pwd)

default:
        $(MAKE) -C $(KERNELDIR) M
=$(PWD) modules

endif


ZelluX 2008-02-10 12:34 发表评论
]]>
LW记(1) - 内核模块http://m.tkk7.com/zellux/archive/2008/02/07/179428.htmlZelluXZelluXThu, 07 Feb 2008 03:22:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/07/179428.htmlhttp://m.tkk7.com/zellux/comments/179428.htmlhttp://m.tkk7.com/zellux/archive/2008/02/07/179428.html#Feedback3http://m.tkk7.com/zellux/comments/commentRss/179428.htmlhttp://m.tkk7.com/zellux/services/trackbacks/179428.htmlinclude/linux/module.h
struct module:
struct module
{
    
// 用于在用L(fng)间传入module对象时判断传入的l构是否有效
    unsigned long size_of_struct;    /* == sizeof(module) */
    
struct module *next;
    
// 指向本module的名Uͼ通常内核I间里申L(fng)name内存位置都是紧跟在module{}l构后面?/span>
    const char *name;
    
// 本module{}l构的空?nbsp;+ 紧接着q段内存甌的归module{}l构使用的一部分I间
    
// size = sizeof(struct module) + sizeof(misc data)
    unsigned long size;

    
// 模块引用计数器,q没搞清楚这里的pad是干什么用?br />     // i386中atomic_t的定? typedef struct { volatile int counter; } atomic_t;
    union
    
{
        atomic_t usecount;
        
long pad;
    }
 uc;                /* Needs to keep its size - so says rth */

    
// 模块当前状态,已初始化/q行?被移?被访问过{?/span>
    unsigned long flags;        /* AUTOCLEAN et al */

    
// 定义的内核模块符h
    unsigned nsyms;
    
// 引用的模块链表节Ҏ(gu)Q遍历模块依赖性时使用
    unsigned ndeps;

    
// W号?/span>
    struct module_symbol *syms;
    
// 记录依赖的其他模块的数组
    struct module_ref *deps;
    
// 记录引用该模块的其他模块的数l?/span>
    struct module_ref *refs;
    
// 初始化和删除模块时调用的函数指针
    int (*init)(void);
    
void (*cleanup)(void);
    
// 中断向量表的入口和结束位|?/span>
    const struct exception_table_entry *ex_table_start;
    
const struct exception_table_entry *ex_table_end;
#ifdef __alpha__
    unsigned 
long gp;
#endif
    
/* Members past this point are extensions to the basic
       module support and are optional.  Use mod_member_present()
       to examine them.  
*/

    
// q两个指针维持一些模块相关信息,方便卸蝲后再ơ装载模块时的配|?/span>
    const struct module_persist *persist_start;
    
const struct module_persist *persist_end;
    
int (*can_unload)(void);
    
int runsize;            /* In modutils, not currently used */
    
const char *kallsyms_start;    /* All symbols for kernel debugging */
    
const char *kallsyms_end;
    
const char *archdata_start;    /* arch specific data for module */
    
const char *archdata_end;
    
const char *kernel_data;    /* Reserved for kernel internal use */
}
;

struct module_symbol:
保存目标代码中的内核W号Q读取文件装入模块时通过q个数据l构里面包含的W号信息d?br />
struct module_symbol
{
    unsigned 
long value; // 入口地址
     const char *name;    // 内核W号名称
}
;

struct module_ref:
注意q里dep和ref记录的不对称Q应该可以看成是一个ref链表?br /> module{} 中的deps数组分别指向?jin)各个依赖的module_ref{}
struct module_ref
{
    
struct module *dep;    /* "parent" pointer */
    
struct module *ref;    /* "child" pointer */
    
struct module_ref *next_ref;
}
;

struct kernel_sym:
在sys_get_kernel_syms()中用到的l构Q该函数内核符h贝到用户I间的kernel_sym{}中,从而可以在用户态存放模块信息?br />
struct kernel_sym
{
    unsigned 
long value;    // 内核W号地址
    char name[60];        /* should have been 64-sizeof(long); oh well */
}
;

module.c中的一些函数先略去?jin),书上蛮详l的

模块的加载和卸蝲
insmod的Q务:(x)
从命令行中读入模块名Q确定代码所在文件的位置
计算需要的内存
执行pȝ调用create_module()Q传递新模块的名U和大小
用QM_MODULES获得所有已l链接模块的模块?br /> 用QM_SYMBOL获得内核W号表和已经链接到内核的模块的符可
使用q些信息重新定位该模块文件中的代?br /> 在用L(fng)间分配内存,拯相关信息
调用sys_init_module()Q传递上面创建的用户态的内存区地址
释放用户态内存,l束

rmmod的Q务:(x)
用QM_MODULES和QM_REFS取得已经链接的模块列表和依赖关系
调用delete_module

ZelluX 2008-02-07 11:22 发表评论
]]>
Linux 内核相关资料链接http://m.tkk7.com/zellux/archive/2008/02/06/179405.htmlZelluXZelluXWed, 06 Feb 2008 11:00:00 GMThttp://m.tkk7.com/zellux/archive/2008/02/06/179405.htmlhttp://m.tkk7.com/zellux/comments/179405.htmlhttp://m.tkk7.com/zellux/archive/2008/02/06/179405.html#Feedback5http://m.tkk7.com/zellux/comments/commentRss/179405.htmlhttp://m.tkk7.com/zellux/services/trackbacks/179405.html 如果一些文章的链接失效Qgoogle相应的标题应该还是很Ҏ(gu)扑ֈ其他|站的{载的?br />

中断处理Q?/strong>
Interrupt in Linux
相当不错的中文资?br />

内核调度Q?/strong>
Inside the Linux scheduler
 
讲的是用expired/active两个数组l护的O(1)法Q大多数?.6内核的书上都?x)提到的调度?(2008-02-06)

Multiprocessing with the Completely Fair Scheduler
最新的2.6.23采用的CFSQ还没搞?(2008-02-06)

http://www.ibm.com/developerworks/cn/linux/l-cn-scheduler/index.html
Linux 调度器发展简q?(2008-02-13)

内核模块Q?br />2.6 内核中的模块注入 (2008-02-17)
http://www.linuxforum.net/forum/showflat.php?Cat=&Board=security&Number=536404&page=0&view=collapsed&sb=5&o=31&fpart

pȝ调用Q?/strong>
Linux 2.6 新增?vsyscall pȝ服务调用机制 (2008-02-18)
http://blog.csdn.net/wishfly/archive/2005/01/23/264435.aspx

Linux on-the-fly kernel patching without LKM (2008-02-19)
http://doc.bughunter.net/rootkit-backdoor/kernel-patching.html

内存理Q?br />http://linux-mm.org/LinuxMM
Linux-mm.org is a wiki for documenting how memory management works and for coordinating new memory management development projects. (2008-02-21)

q发同步Q?/strong>
http://hi.baidu.com/charleswen/blog/item/61f3e40ebc26dcce7acbe1c8.html
Linux内核中的同步和互斥分析报?(2008-02-21)

http://www-128.ibm.com./developerworks/cn/linux/kernel/sync/index.html
Linux 2.4.x内核同步机制 (2008-02-22)

Big Picture:
http://www.linuxdriver.co.il/kernel_map
Interactive Linux kernel map (2008-02-16)
把内怸的函数相互调用做成了(jin)一张可攑֤~小的地图,单击相应函数名会(x)跌{到l(f)xr的相应代码链接?

~程资料Q?br />http://www.jegerlehner.ch/intel/
Intel Assembler CodeTable 80x86 (2008-02-21)

相关站点Q?br />http://kernelnewbies.org
Linux Kernel Newbies

http://bbs4.newsmth.net/bbsdoc.php?board=KernelTech
水木KernelTech?br />
http://www.phrack.org
Phrack is an underground ezine made by and for hackers.
有不和内核相关的hack资料



ZelluX 2008-02-06 19:00 发表评论
]]>
Inside the Windows Vista Kernelhttp://m.tkk7.com/zellux/archive/2007/12/21/169311.htmlZelluXZelluXFri, 21 Dec 2007 07:07:00 GMThttp://m.tkk7.com/zellux/archive/2007/12/21/169311.htmlhttp://m.tkk7.com/zellux/comments/169311.htmlhttp://m.tkk7.com/zellux/archive/2007/12/21/169311.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/169311.htmlhttp://m.tkk7.com/zellux/services/trackbacks/169311.htmlhttp://www.microsoft.com/technet/technetmag/issues/2007/03/VistaKernel
http://www.microsoft.com/technet/technetmag/issues/2007/03/VistaKernel
http://www.microsoft.com/technet/technetmag/issues/2007/03/VistaKernel


ZelluX 2007-12-21 15:07 发表评论
]]>
关于矩阵乘法的优?/title><link>http://m.tkk7.com/zellux/archive/2007/12/06/165777.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Thu, 06 Dec 2007 05:17:00 GMT</pubDate><guid>http://m.tkk7.com/zellux/archive/2007/12/06/165777.html</guid><wfw:comment>http://m.tkk7.com/zellux/comments/165777.html</wfw:comment><comments>http://m.tkk7.com/zellux/archive/2007/12/06/165777.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/zellux/comments/commentRss/165777.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/zellux/services/trackbacks/165777.html</trackback:ping><description><![CDATA[CS:APP P521<br /> 在CC同学的帮助下l于看懂q个E序?br /> 关键在于P488的Generic Cache Memory OrganizationQ以前看q,没留下什么印?br /> cache是有多个(2<sup>s</sup>个)(j)大小为block size的片l成?br /> q样在访问B[k][j]ӞB[k][j] - B[k][j + bsize - 1]q条内存pcache?br /> 重复bsizeơ后B[k][k] - b[k + bsize - 1][k + bsize - 1]q块内存被cache<br /> 后面做乘法就快很多的<br /> <img src ="http://m.tkk7.com/zellux/aggbug/165777.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/zellux/" target="_blank">ZelluX</a> 2007-12-06 13:17 <a href="http://m.tkk7.com/zellux/archive/2007/12/06/165777.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内核中的Listl构http://m.tkk7.com/zellux/archive/2007/10/12/152279.htmlZelluXZelluXFri, 12 Oct 2007 03:38:00 GMThttp://m.tkk7.com/zellux/archive/2007/10/12/152279.htmlhttp://m.tkk7.com/zellux/comments/152279.htmlhttp://m.tkk7.com/zellux/archive/2007/10/12/152279.html#Feedback4http://m.tkk7.com/zellux/comments/commentRss/152279.htmlhttp://m.tkk7.com/zellux/services/trackbacks/152279.html发信? CJC (蓝色雪狐), 信区: 05SS
?nbsp; ? OS_Lab3 指南 List
发信? 复旦燕曦BBS (2007q?0?1?3:55:12 星期?, 转信

    先写点List的东西吧Q这个其实在以前q不作ؓ(f)重点Ԍ不过好像大家对它q是有些?br /> 见,所以这ơ稍微讲下吧。作用是为到时候徏立进E关pd表做准备?br />     讲的内容都在/usr/src/linux.../include/linux/list.h中,大家只要把一些不必要?br /> ifdef和一些prefetch的东西删掉就好了(jin)?br />
    首先讲讲历史。在没有范型的Java里面我们用的链表往往?x)这P如果转成C的话Q:(x)
typedef struct list_head {
    struct list_node *prev;
    void *data;
    struct list_node *next;
} list_t;
    通过q个l构Q我们就能完成链表的功能?jin)。但是我觉得q个数据l构不好Q原因有?br /> Q?br />     W一Q这个结构比较容易引起内存碎片?br />     ┌──┬─┬──?br />     │prev?nbsp; │next?lt;----多余内存消?br />     └──┴┼┴──?br />             ?nbsp;  ┌───?br />             └─>?data ?br />                  └───?/span>
    q种设计每一个节炚w?x)引起一块多余的内存消耗?br />
    W二Q类型不明确Q因为现在没办法用范型。如果写明了(jin)cdQ那么还要ؓ(f)每种cd?br /> list自己再做一整套函数Q得不偿失?br />
    当然Q还?x)考虑cM于我们希望用别h写得比较好的代码之类的原因?br />
    那让我们来看看我们版本里的list_t是怎么定义?br /> typedef struct list_head {
    struct list_head *next, *prev;
} list_t;
    乍一看,q个list_head里面什么都没包含,只有一对前后指针,没有指向数据的指?br /> 。那怎么用呢Q这里的做法我叫做:(x)反包含。我们来看一个具体的使用例子Q?br /> typedef struct test_struct {
    int val1;
    int val2;
    char vals[4];
    list_t all_tests;   //千万注意Q这里是list_tQ不是list_t *
} test_t;

    那么我们声明?jin)这个数据结构在内存中是什么样的呢Q?br />  (test_list)         ┌─────┐┬    <--my_test_struct_p(test_t *)
┌──┬──?nbsp;      ?nbsp;  val1   ││
│prev│next├┐     ├─────┤│
└──┴──┘│     ?nbsp;  val2   ││h
              ?nbsp;    ├─────┤│
              ?nbsp;    ?nbsp;  vals   ││
表示指向首地址└──>├──┬──┤┴    <--my_list_p(list_t *)
                     │prev│next?nbsp;     //q里如果是list_t *׃是这L(fng)?jin)?br style="font-family: " />                      └──┴──?/span>
    上图是一个test_t的结构图。小地址在上Q大地址在下Qval1上面的那条分界线作ؓ(f)
val1的v始地址Q请注意我my_test_struct_p?qing)其它指针的LQ是指向上面那根U,表示
为那个东西的起始地址Qؓ(f)清楚赯推荐大家以后q样画)(j)
    然后Z(jin)把所有的test_t数据l构串v来,我们需要一个全局变量Qtest_listQ类?br /> 为list_tQ如果这里声明list_t *的话一定要为它分配I间Q如果是ȝ全局变量、全局?br /> l和一些(f)时数l,推荐直接声明成类型而不是指针,因ؓ(f)~译器会(x)攑֜dat/bss和stackD?br /> 里。但是如果这个数据结构是q回cd的分配空_(d)一定要malloc!否则回去׃(x)错。这?br /> 也提醒一下)(j)
    我们可以看到test_list.next是指向my_test_struct_p->all_testsQ而不是my_test_s
truct。但是对我有用的应该是my_test_struct。所以一般处理方法有二,
    W一U比较死板,是在数据结构的一开始就放一个list_tQ命名ؓ(f)listQ,那么&lis
t=&struQ可以直?xxx *)list_p。但是问题是如果一个数据结构可以同属两个链表,如pc
bQ又要是run_list的成员,又要是all_tasks的成员,q要是父q程children的成?#8230;…q?br /> U方法显然是不够的?br />     W二U方法就相对好些。大家可以看Q?br />     ((unsigned int)my_list_p)-h=(unsigned int)my_test_struct_p
    而怎么得到h呢?是不是需要每个数据结构都定义一个h呢?不需要,可以q样?br />     h=(unsigned int)(&(((test_t *)0)->all_tests))
    是?地址当作是test_t数据l构的开始地址Q那么这个数据结构的all_tests所在的
地址是h?jin)?br />     通过把这两个式l合Q我们可以得C个宏Q?br /> #define list_entry(ptr, type, member) \
    ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
    在这里的用法是Q?br />     my_test_struct_p = list_entry(test_list.next, test_t, all_tests);
    Q如果用类gSimics的编辑器的话Qall_tests的显CZ(x)是类g没有定义变量Q?br /> 不用它Q的是q样的。最后编译成功就对了(jin)Q?br />     看过?jin)最_֦的list_entry之后我们可以来看一些简单的操作?br /> #define INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
    Z么要加while(0)可以参见lab2指南里面的一些define帮助。其大致概念如下Q?br /> ┌─────────?br style="font-family: " /> ?nbsp;                 ?br style="font-family: " /> ?>┌──┬──?nbsp; ?br style="font-family: " /> ┌─┤prev│next├─?nbsp;    //q里Z(jin)L逻辑Q不把指针放在首地址
?nbsp; └──┴──?lt;-?br style="font-family: " /> ?nbsp;                 ?br style="font-family: " /> └─────────?/span>
    q是一个环犉表。一般这个作为头指针Q链表ؓ(f)I的判断依据是Q?br /> static inline int list_empty(struct list_head *head)
{
    return head->next == head;
}
    然后是添加,先有一个辅助函敎ͼ(x)
static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}
    q个是添加在W一个:(x)
static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}
┌───────────────────?br style="font-family: " /> ?nbsp;                    ┌─────?nbsp;  ?br style="font-family: " /> ?>┌──┬──┐┌─>├──┬──?nbsp;  ?br style="font-family: " /> ┌─┤prev│next├┘ ┌┤prev│next?─?nbsp; //q里的数据结构就省略M(jin)
?nbsp; └──┴──?lt;─┘├──┴──?<-?br style="font-family: " /> ?nbsp;                    └─────?nbsp;  ?br style="font-family: " /> └───────────────────?/span>
                          ori_first
┌────────────────────────────?br style="font-family: " /> ?nbsp;                    ┌─────?nbsp;    ┌─────?nbsp; ?br style="font-family: " /> ?>┌──┬──┐┌─>├──┬──┤┌─>├──┬──?nbsp; ?br style="font-family: " /> ┌─┤prev│next├┘ ┌┤prev│next├┘ ┌┤prev│next├─?br style="font-family: " /> ?nbsp; └──┴──?lt;─┘├──┴──?lt;─┘├──┴──?lt;-?br style="font-family: " /> ?nbsp;                    └─────?nbsp;    └─────?nbsp; ?br style="font-family: " /> └────────────────────────────?/span>
                            new             ori_first

    q个是添加在head->prevQ由于是环状的,那么是d?jin)最后一?br /> static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}
┌────────────────────────────?br style="font-family: " /> ?nbsp;                    ┌─────?nbsp;    ┌─────?nbsp; ?br style="font-family: " /> ?>┌──┬──┐┌─>├──┬──┤┌─>├──┬──?nbsp; ?br style="font-family: " /> ┌─┤prev│next├┘ ┌┤prev│next├┘ ┌┤prev│next├─?br style="font-family: " /> ?nbsp; └──┴──?lt;─┘├──┴──?lt;─┘├──┴──?lt;-?br style="font-family: " /> ?nbsp;                    └─────?nbsp;    └─────?nbsp; ?br style="font-family: " /> └────────────────────────────?br style="font-family: " />                          ori_first             new

    接下来是删除Q?br />     q是辅助Ҏ(gu)
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
    next->prev = prev;
    prev->next = next;
}
    q个是用?jin)辅助方法__list_delq且把entry的前后都设ؓ(f)NULLQ是Z(jin)安全赯
static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = (void *) 0;
    entry->prev = (void *) 0;
}
    个h觉得list_del_init, list_move, list_move_tail, list_splice没啥太大作用…
…不过后面两个非常重要Q?br /> #define list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_prev(pos, head) \
    for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
            pos = pos->prev, prefetch(pos->prev))

使用Ҏ(gu)Q?br /> list_t *pos;
list_for_each(pos, &test_list) {
    test_t *tmp = list_entry(pos, test_t, all_tests);
    //do something on tmp
}
=======================================================================
list_t *pos, *n;
list_for_each_safe(pos, n, &test_list) {
    test_t *tmp = list_entry(pos, test_t, all_tests);
    //do something on tmp
}
======================================================================
    那么q两个有什么差别呢Q我们可以来看这个例子:(x)
list_for_each(pos, &test_list) {
    list_del(pos);
}
    首先Q我们得到pos=test_list.nextQ然后删除,此时pos->next=0Q如果按照list_fo
r_each的话下一个@环的pos是NULLQ再讉K下去出错了(jin)Q同L(fng)Q修改位|也是。所
以在需要修攚w列结构的时候,一定要使用list_for_each_safe。如果只修改对应的数据结
构其他字D,可以用list_for_eachQ因个效率比较高?br />
    有了(jin)q些Ҏ(gu)基本上就可以使用?jin)。我们可以来看一个物理内存管理的例子Q?br /> #define USER_MEM_SIZE (256*1024*1024)
#define USER_MEM_START (16*1024*1024)
#define PAGE_SHIFT 12
#define PAGE_SIZE (1<<(PAGE_SHIFT))
#define PAGE_COUNT (((USER_MEM_SIZE)-(USER_MEM_START))>>(PAGE_SHIFT))
#define PAGE_START(ptr) (((ptr)-(all_pages))<<(PAGE_SHIFT)+(USER_MEM_START))
//获取q个page数据l构对应的v始地址
#define PAGE_STRU(addr) (&all_pages[((addr)-(USER_MEM_START))<<(PAGE_SHIFT)])

typedef struct page_struct {
    unsigned long use_count;
    list_t mem_list;
} page_t;

list_t free_list, lru_list; //lru是用作换出的Q最q用在队首Q换出队N
//如果~译器不肯让我们q样定义的话用lmm_alloc或者out_alloc也可以?br /> page_t all_pages[PAGE_COUNT];

void init()
{
    int i;
    INIT_LIST_HEAD(&free_list);
    INIT_LIST_HEAD(&lru_list);      //初始化两个链?br />     for (i = 0; i < PAGE_COUNT; i++) {
        all_pages[i] = 0;
        list_add_tail(&all_pages[i].mem_list, &free_list);  //加入free_list
    }
}

//此处q回g为错误信息,addr作ؓ(f)所需q回的物理内存v始地址
int get_page(unsigned int *addr)
{
    if (list_empty(&free_list)) //没有I页
        return -1;
    list_t *lst = free_list.next;
    list_del(lst);
    list_add(lst, &lru_list);   //最q用,攑ֈ队首
    *addr = PAGE_START(list_entry(lst, page_t, mem_list);
    return 0;
}

void use_page(unsigned int addr)
{
    page_t *pg = PAGE_STRU(addr);
    list_del(&pg->mem_list);
    list_add(&pg->mem_list, &lru_list); //页面放到l(f)ru队列?br /> }

void return_page(unsigned int addr)
{
    page_t *pg = PAGE_STRU(addr);
    list_del(&pg->mem_list);
    list_add(&pg->mem_list, &free_list); //页面放到free队列首,下次取时?br /> }

    物理面理基本上就cM于此。我们接下来来看一个稍微复杂些的例子,是q程?br /> 子关pȝ例子Q去q又同学跟我反映q是一个交错链接或者说是嵌套链接,其实不然。我?br /> 拆分开来看Q?br />          ┌─────────-?br style="font-family: " />          │┌-────────┼───?br style="font-family: " />          ??A->children    ?nbsp;     ?br style="font-family: " /> ┌───-┼─>┌──┬──?nbsp; ?nbsp;     ?br style="font-family: " /> ?nbsp;      ?─┤prev│next├┐?nbsp;     ?br style="font-family: " /> ?nbsp;           └──┴──┘│?nbsp;     ?br style="font-family: " /> │┌────────────┘│      ?br style="font-family: " /> ││                 ?───?nbsp;     ?br style="font-family: " /> ││ ┌─────?nbsp;  ↘┌─────┐│
│└>├──┬──┤┌─>├──┬──┤│
?─┤prev│next├┘ ┌┤prev│next├┘
     ├──┴──?lt;─┘├──┴──?br style="font-family: " />      └─────?nbsp;    └─────?br style="font-family: " />            B                  C

    由图可知QA有BC两个子进E,分别q接到Aq程的children上。此Ӟ处理A的childre
n又有两种Ҏ(gu)Q第一U是增加指针Q第二种是作为Aq程的一部分。利用上面的思考方法,
我们可以知道Q如果按照第一U做法,那么势必?x)引h多的内存片Q不方便。于是我?br /> 把children作ؓ(f)pcb的一个field。那么B和C里面的prev/next该叫什么呢Q因为B和C也是pc
b的数据结构,已经不可能再叫children?jin)(而且他们也应该有children节点Q因Z们也
可能有子q程Q。那么我们就叫它为sibling吧。因为在q个链表里,除了(jin)A是父q程Q其?br /> 的都是兄弟进E?br />     所以pcb的父子关pd以这样写Q?br /> #define TASK_STATE_RUNNING 0
#define TASK_STATE_ZOMBIE 1
//调用?jin)wait指o(h)Q等待子q程l束
#define TASK_STATE_WAIT_CHILD 2

typedef struct pcb_struct{
    struct pcb_struct *parent;  父进E?br />     unsigned long state;
    list_t children;
    list_t sibling;
    list_t all_tasks;
} pcb_t;

//init是一个非常特D的q程Q一般我们的kernel一hQ就只负责两个进E:(x)init和idle
//init的作用是先forkQ子q程q行shellQ它自nwhile(1) {wait(...);}是负责回收
//孤儿q程?br /> //q且在此Q我们可以把所有的q程都连接在init的all_tasks上面Q这样又可以节省一?br /> //相当于前例test_list的全局变量。找所有进E只遍历init->all_tasks卛_?br /> //所以在生成init的时候应该是INIT_LIST_HEAD(&task->all_tasks)
void init_pcb(pcb_t *task, pcb_t *init)
{
    INIT_LIST_HEAD(&task->children);
    INIT_LIST_HEAD(&task->sibling);
    task->parent = NULL;
    task->state = TASK_STATE_RUNNING;
    list_add_tail(&task->all_tasks, &init->all_tasks);
}

void add_child(pcb_t *parent, pcb_t *child)
{
    child->parent = parent;
    list_add_tail(&child->sibling, &parent->children);  //xZ?br /> }

void do_exit(pcb_t *task, pcb_t *init)
{
    //exit_mem_first_part
    list_t *pos, *n;
    list_for_each_safe(pos, n, &task->children) //所有子q程交给init
    {           //~~~~
        task_t *child = list_entry(pos, task_t, sibling); //q里是sibling
        child->parent = init;
        list_del(&child->sibling);
        list_add_tail(&child->sibling, &init_children);
        if (child->state == TASK_STATE_ZOMBIE && init->state != TASK_STATE_WAIT_
CHILD)
        {
            //q里ȀzinitQƈ把init攑ֈq程列表的尾?br />         }
    }
    //然后切换到父q程q行
}
    如果看懂?jin)以上的所有例子,那么链表l构应该差不多?jin)。由于篇q关p,PCB的构
建就单列开来吧。这里专门讲LIST好了(jin)?)
    如果有代码觉得看的郁L(fng)Q拿张纸ȝ对应的内存结构应该就?x)好些?jin)
--

?修改:·CJC ?Oct 11 03:57:46 修改本文·[FROM: I梭而来]
?来源:·复旦燕曦BBS yanxibbs.cn·[FROM: I梭而来]


ZelluX 2007-10-12 11:38 发表评论
]]>
Linux核心(j)源码的目录结?/title><link>http://m.tkk7.com/zellux/archive/2007/10/04/150384.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Thu, 04 Oct 2007 09:26:00 GMT</pubDate><guid>http://m.tkk7.com/zellux/archive/2007/10/04/150384.html</guid><wfw:comment>http://m.tkk7.com/zellux/comments/150384.html</wfw:comment><comments>http://m.tkk7.com/zellux/archive/2007/10/04/150384.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/zellux/comments/commentRss/150384.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/zellux/services/trackbacks/150384.html</trackback:ping><description><![CDATA[以下转蝲自《Linux kernel?br /> <br /> 核心(j)源码的顶层是/usr/src/linux目录Q在此目录下你可以看到大量子目录Q?br /> arch<br /> q个子目录包含了(jin)所有体pȝ构相关的核心(j)代码。它q包含每U支持的体系l构的子目录Q如i386?br /> include<br /> q个目录包括?jin)用来重构核心(j)的大多数include文g。对于每U支持的体系l构分别有一个子目录?nbsp;此目录中的asm子目录中是对应某U处理器的符可接,如include/asm-i386。要修改处理器结?nbsp;则只需~辑核心(j)的makefileq新运行Linux核心(j)配置E序?br /> init<br /> 此目录包含核?j)启动代码?br /> mm<br /> 此目录包含了(jin)所有的内存理代码。与具体体系l构相关的内存管理代码位于arch/*/mm目录下, 如arch/i386/mm/fault.c ?br /> drivers<br /> pȝ中所有的讑֤驱动都位于此目录中。它又进一步划分成几类讑֤驱动Q如block?br /> ipc<br /> 此目录包含了(jin)核心(j)的进E间通讯代码?br /> modules<br /> 此目录仅仅包含已建好的模块?br /> fs<br /> 所有的文gpȝ代码。它也被划分成对应不同文件系l的子目录,如vfat和ext2?br /> kernel<br /> 主要核心(j)代码。同时与处理器结构相关代码都攑֜arch/*/kernel目录下?br /> net<br /> 核心(j)的网l部分代码?br /> lib<br /> 此目录包含了(jin)核心(j)的库代码。与处理器结构相兛_代码被放在arch/*/lib/目录下?br /> scripts<br /> 此目录包含用于配|核?j)的脚本文gQ如awk和tk脚本Q?nbsp;<br /> <img src ="http://m.tkk7.com/zellux/aggbug/150384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/zellux/" target="_blank">ZelluX</a> 2007-10-04 17:26 <a href="http://m.tkk7.com/zellux/archive/2007/10/04/150384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CSAPP - Explicitly Blocking Signals http://m.tkk7.com/zellux/archive/2007/09/05/142862.htmlZelluXZelluXWed, 05 Sep 2007 04:22:00 GMThttp://m.tkk7.com/zellux/archive/2007/09/05/142862.htmlhttp://m.tkk7.com/zellux/comments/142862.htmlhttp://m.tkk7.com/zellux/archive/2007/09/05/142862.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/142862.htmlhttp://m.tkk7.com/zellux/services/trackbacks/142862.html
#include <signal.h>

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);              // Return: 0 if OK, -1 on error
int sigismember(const sigset_t *set, int signum);      // Return: 1 if member, 0 if not, -1 on error

sigprocmask用于改变当前blocked signals的集合,how参数指定?jin)具体的行?f)Q?br /> SIG_BLOCK 把set中的信号d到blocked列表(blocked = blocked | set)
SIG_UNBLOCK 把set中的信号从blocked列表中移?blocked = blocked & ~set)
SIG_SETMASK blocked = set

另外Q如果oldset的g是NULL的话Q之前的blocked列表?x)保存在oldset中?br />
而sigaddset sigdelset sigfillset sigemptyset都是用于操作sigset_t列表的函数?br />
sigprocmask适用于在父子q程间同步的情况Q以一个典型的UNIX shellE序ZQ父q程需要在一个job list中记录它所有的子进E,当父q程创徏一个子q程Ӟ它把子进E加入到job list中;当父q程reap一个子q程Ӟ׃job list中移?gu)个进E?br /> 如果不同步父子进E,有可能发生这U情况:(x)
1. 父进E执行fork函数Q内核调度新创徏的子q程替换父进E运?br /> 2. 在父q程能够再次q行前,子进E终止,成ؓ(f)一个zombieQ内核发送SIGCHLD信号l父q程
3. 父进E可以运行前Q内核发C(jin)未处理的(pending)SIGCHLD信号Q让它由父进E的handler处理
4. handler reap?jin)终止的q程Q调用deletejob函数Q实际上没有M作用Q因为父q程q没有把该子q程加入列表
5. handler完成后,内核l箋q行父进E,后者调用fork完成后l,错误地把不存在的子进E加入了(jin)job list

ZelluX 2007-09-05 12:22 发表评论
]]>
CSAPP - Alignmenthttp://m.tkk7.com/zellux/archive/2007/08/10/135947.htmlZelluXZelluXFri, 10 Aug 2007 15:14:00 GMThttp://m.tkk7.com/zellux/archive/2007/08/10/135947.htmlhttp://m.tkk7.com/zellux/comments/135947.htmlhttp://m.tkk7.com/zellux/archive/2007/08/10/135947.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/135947.htmlhttp://m.tkk7.com/zellux/services/trackbacks/135947.html
寚w是指ؓ(f)?jin)提高处理器的效率,把某些基cd的地址规定为必L某个?通常?,4?Q的整数倍?br>如果不这样处理,例如把一个double值分开存放在地址?*n的两边,处理器每ơ从内存中读?字节Q这样就需要读取两ơ才能得到这个doubleg(jin)?br>Linux的做法是?字节数据Q如shortQ存攑֜偶数的地址中,把其他更大的数据Qint, int *, float, doubleQ放在以4为约数的地址中?br>Windows则用了(jin)相对C的处理器而言更好的做法,Mk字节的数据必d攑֜以k的倍数v始的地址中,即double必须存放在以8*nv始的地址中?br>GCC的编译开?malign-double也可以达到这U效果,但因此可能导致与某些假定4字节寚w方式的库的链接错误?br>一个简单的例子Q?br>struct S1 {
    int i;
    char c;
    int j;
};
寚w后的保存方式?br>0-4: i
4-5: c
8-12: j



ZelluX 2007-08-10 23:14 发表评论
]]>
CSAPP - Linking - 动态链接库http://m.tkk7.com/zellux/archive/2007/08/07/135097.htmlZelluXZelluXTue, 07 Aug 2007 15:10:00 GMThttp://m.tkk7.com/zellux/archive/2007/08/07/135097.htmlhttp://m.tkk7.com/zellux/comments/135097.htmlhttp://m.tkk7.com/zellux/archive/2007/08/07/135097.html#Feedback2http://m.tkk7.com/zellux/comments/commentRss/135097.htmlhttp://m.tkk7.com/zellux/services/trackbacks/135097.html 1) ?rn)态库通常需要维护和定期更新Q而这些库的用者就得注意这些变化,q且在库修改后重新将自己的程序和库链接v?br> 2) 以printf和scanfq两个函Cؓ(f)例,它们的代码在每个q行的进E里都保留了(jin)一份,在一个典型的操作pȝ上运行着50-100个进E,q无疑是对系l资源的严重费。(内存的一个有的Ҏ(gu)是Q它永远是一个短~的资源Q无关一个系l里有多大的内存Q?br>
2. ׃n?shared library)弥补?jin)?rn)态库的这些缺陗所谓共享库Q就是指?strong>q行?/strong>可以被读入到L?/strong>内存地址Qƈ与程序链接的模块。这个过E也被称为动态链?dynamic linking)Q由动态链接器(dynamic linker)完成?br> Unixpȝ中共享对象通常后缀?soQ微软的操作pȝ中大量用了(jin)׃n库,通常被称为DLL(dynamic link libraries)

3. ׃n库的“׃n”表现在两个方面:(x)
1) 在Q何一个给定的文gpȝ中,对于某个特定的库Q只有一?so文g
2) ׃n库单独的一?text域可以由多个不同的运行进E共享?br>
4. ~译一个共享库Qgcc -shared -fPIC -o libvector.so addvec.c multvec.c
-fPIC开兌~译器生位|独立的代码(PIC, position independent code)
-shared开关得编译器产生׃n对象的文?br>
5. 动态链接的几个应用Q?br> 1) 软g的分布式开?br> 2) 开发高效的Web服务?br> 早期的Web服务器通过fork和execve调用子进E来产生动态的内容Q被UCؓ(f)CGIQ而现代的Web服务器则通过Z动态链接库的一U高效的方式?br> 主要的方法是把生成动态内容的函数打包C个共享库中,当服务器端接收到一个请求后Q服务器动态地dq且链接到相应的函数Qƈ直接调用q个函数Q? fork和execve则是在子q程的环境中q行的。函数调用后l箋存在Q以后的cMh都只需要一个简单的调用可以了(jin)。另外,Ҏ(gu)也可以在不停止服? 器的情况下更斎ͼ也可以加入新的函数?br>
6. Unixpȝ中读入ƈ链接׃n库的Ҏ(gu)
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
// returns: ptr to handle if OK, NULL on error
需要通过-rdynamic~译Q具体见CSAPP P569

获得已经打开的库的句?handle)
#include <dlfcn.h>
void #dlsym(void *handle, char *symbol);
// returns: ptr to symbol if OK, NULL on error

关闭׃n?br> #include <dlfcn.h>
int dlclose(void *handle);
// returns: 0 if OK, -1 on error

获得错误信息
#include <dlfcn.h>
const char *dlerror(void);

ZelluX 2007-08-07 23:10 发表评论
]]>
CSAPP - Linking - Strong and weak symbolshttp://m.tkk7.com/zellux/archive/2007/08/02/134126.htmlZelluXZelluXThu, 02 Aug 2007 15:45:00 GMThttp://m.tkk7.com/zellux/archive/2007/08/02/134126.htmlhttp://m.tkk7.com/zellux/comments/134126.htmlhttp://m.tkk7.com/zellux/archive/2007/08/02/134126.html#Feedback0http://m.tkk7.com/zellux/comments/commentRss/134126.htmlhttp://m.tkk7.com/zellux/services/trackbacks/134126.html《窃听风暴》的男主角乌?dng)里?#183;I埃(Ulrich Mühe) 病逝了(jin)。。?/span>
好片子,好演员,可惜?jin)。。?/span>

CSAPP W七章Linking太枯燥了(jin)  啃了(jin)半天ȝ看到一点实际经历中遇到q的?br>
在编译阶D,~译器把全局变量标记为strong或者weakQƈ导出到汇~程序中Q由汇编E序把这些信息隐式地d到relocatable object file的符可(symbol table)中?br>函数和被初始化的全局变量被标Cؓ(f)strongQ未初始化的全局变量被标Cؓ(f)weak?br>Unixq接?linker)使用下面的规则来处理多个W号的情况:(x)
1. 不允许多个strong symbol的存?br>2. 如果有一个strong symbol和若q个weak symbolQ用strong symbol
3. 只有若干个weak symbolQ则使用其中L一?br>
几个例子Q未Ҏ(gu)说明的情况,变量定义均在全局范围Q:(x)
1. foo1.c和bar1.c中都有int main()Ҏ(gu)Q即存在?jin)两个strong symbolQ连接器׃(x)产生一条错误信息?br>2.
/* foo3.c */
#include 
<stdio.h>
void f(void);

int x = 15213;

int main()
{
    f();
    printf(
"x = %d\n", x);
    
return 0;
}

/* bar3.c */
int x;

void f()
{
    x 
= 15212;
}
main()Ҏ(gu)调用f()后,x变ؓ(f)15212q被输出?br>注意q可能不是main()Ҏ(gu)的作者原来的意图?/span>
cM的情况也可能发生在两个weak symbol同名的时候?br>
3. 全局变量cd不同的情况:(x)
/* foo5.c */
#include 
<stdio.h>
void f(void);

int x = 15213;
int y = 15212;

int main()
{
    f();
    printf(
"x = 0x%x  y = 0x%x \n", x, y);
    
return 0;
}

/* bar4.c */
double x;

void f()
{
    x 
= -0.0;
}
Ҏ(gu)书上的内容,
linux> gcc -o foobar5 foo5.c bar5.c
linux> ./foobar5
l果应该?br>x = 0x0  y = 0x80000000

但是在自己机器上~译时报错了(jin)Q可能连接器版本较高Q会(x)自动扑ևq种错误
/usr/bin/ld: Warning: alignment 4 of symbol `x' in /tmp/ccupQXSG.o is smaller than 8 in /tmp/ccNNG9XZ.o
是double和int大小不义D的对齐问?br>

q些问题都比较细难以被查觉Q通常在程序执行了(jin)一D|间后才出现较严重的问题,因此很难被修复,其当许多程序员不清楚连接器的工作方式的时候?br>另外可以使用GCC?warn-common标记(flag)Q得它在解析多个同名的全局变量时发?gu)告?br>试了(jin)下没成功@@
gcc --warn-common提示无法识别的命令行选项Qgcc -Wall则不?x)发(gu)告?br>

ZelluX 2007-08-02 23:45 发表评论
]]>
վ֩ģ壺 Ʒۺ| 鶹Ƶѹۿ| ľþþƷ| һ߹ۿƵ| Ұһ| ޺ݺۺϾþ| ҹѸӰԺ| һ23456| ĻmvֻѸ | 18վ| ޾Ʒ鶹ר| mvߵӰ| ؼaaaaaaëƬ| ĻmvѸƵ8| 컶ëƬ| ձѾþþþþþվ| AVһ | ޾Ʒ߹ۿ| ҪѵëƬ| ŷa߹ۿ| ֻѸۿ| ޹һ߹ۿ| Ļѹۿ| һ߹ۿ| ˾Ʒþ޸岻 | þ99Ʒһ| ޾ƷþþӰԺӰƬ| WWWƵ| þþƷ㽶| 99re6ƵƷѹۿ| ۺϾþþþþĻ| þó˹Ʒ| ɫ͵͵Ůùۿŷ| ҹڵ| ɫۺ㽶| ޵һҳۺͼƬ| Ļ߳ѿ| ޾ƷԲ߹ۿ| ŮƵ| ӰԺavɫ| ߹ۿɫëƬ|