Posted on 2012-10-15 10:37
鑫龍 閱讀(583)
評(píng)論(0) 編輯 收藏 引用 所屬分類(lèi):
linux內(nèi)核
Linux通過(guò)slab分配器動(dòng)態(tài)分配task_struct結(jié)構(gòu),該結(jié)構(gòu)定義在了<include/linux/sched.h>文件中,進(jìn)程描述符中包含一個(gè)具體進(jìn)程的所有信息,各個(gè)進(jìn)程的task_struct存放在它們內(nèi)核棧的尾端。在棧底(對(duì)于向下增長(zhǎng)的棧)或棧頂(對(duì)于向上增長(zhǎng)的棧)創(chuàng)建一個(gè)新的結(jié)構(gòu)struct thread_info。利用這個(gè)新的機(jī)構(gòu)來(lái)迅速的找到task_struct的位置。 下面是kernel2.6.32.10里task_struct的定義(對(duì)于x86類(lèi)型的CPU來(lái)說(shuō)文件位于:arch/x86/include/asm /include/asm/thread_info.h):- struct thread_info {
- struct task_struct *task; /* main task structure */
- struct exec_domain *exec_domain; /* execution domain */
- __u32 flags; /* low level flags */
- __u32 status; /* thread synchronous flags */
- __u32 cpu; /* current CPU */
- int preempt_count; /* 0 => preemptable, <0 => BUG */
- mm_segment_t addr_limit;
- struct restart_block restart_block;
- void __user *sysenter_return;
- #ifdef CONFIG_X86_32
- unsigned long previous_esp; /* ESP of the previous stack in case of nested (IRQ) stacks*/
- __u8 supervisor_stack[0];
- #endif
- int uaccess_err;
- };
其中的task的值就為task_struct的位置。kernel利用current宏尋找task_struct的位置,假設(shè)棧的大小為8k(13個(gè)二進(jìn)制位),我們可以將進(jìn)程棧的地址的后13位屏蔽掉,這樣得到的剛好就是進(jìn)程棧的起始地址,而thread_info剛好就是位于進(jìn)程棧的底部,所以進(jìn)程棧的起始地址就是struct thread_info的地址,得到了thread_info的地址,我們就很容易找到task_struct的地址了。匯編實(shí)現(xiàn)過(guò)程為movl %-8192 ,%eaxandl %esp ,%eax寄存器esp存放進(jìn)程棧的當(dāng)前地址,eax最后存放的就是進(jìn)程棧的起始地址。current使用current_thread_info來(lái)實(shí)現(xiàn)這個(gè)過(guò)程。kernel源碼(對(duì)于x86類(lèi)型的CPU來(lái)說(shuō)文件位于arch/x86/include/asm //include/asm/thread_info.h)- /* how to get the current stack pointer from C */
- register unsigned long current_stack_pointer asm("esp") __used;
- /* how to get the thread information struct from C */
- static inline struct thread_info *current_thread_info(void)
- {
- return (struct thread_info *)
- (current_stack_pointer & ~(THREAD_SIZE - 1));
- };
其中current_stack_pointer為進(jìn)程棧的當(dāng)前地址,THREAD_SIZE為進(jìn)程棧的大小。所以current_thread_info()->task即為task_struct()的地址。