Posted on 2012-10-15 10:37
鑫龍 閱讀(580)
評論(0) 編輯 收藏 引用 所屬分類:
linux內核
Linux通過slab分配器動態分配task_struct結構,該結構定義在了<include/linux/sched.h>文件中,進程描述符中包含一個具體進程的所有信息,各個進程的task_struct存放在它們內核棧的尾端。在棧底(對于向下增長的棧)或棧頂(對于向上增長的棧)創建一個新的結構struct thread_info。利用這個新的機構來迅速的找到task_struct的位置。 下面是kernel2.6.32.10里task_struct的定義(對于x86類型的CPU來說文件位于: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的位置,假設棧的大小為8k(13個二進制位),我們可以將進程棧的地址的后13位屏蔽掉,這樣得到的剛好就是進程棧的起始地址,而thread_info剛好就是位于進程棧的底部,所以進程棧的起始地址就是struct thread_info的地址,得到了thread_info的地址,我們就很容易找到task_struct的地址了。匯編實現過程為movl %-8192 ,%eaxandl %esp ,%eax寄存器esp存放進程棧的當前地址,eax最后存放的就是進程棧的起始地址。current使用current_thread_info來實現這個過程。kernel源碼(對于x86類型的CPU來說文件位于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為進程棧的當前地址,THREAD_SIZE為進程棧的大小。所以current_thread_info()->task即為task_struct()的地址。