一个简单的问题,·linux下获取当前进程。我们都知道在内核中获取当前进程可以利用current宏
#define get_current() (current_thread_info()->task) #define current get_current()
通过get_current发现其是利用当前线程获取的当前进程线程结构thread_info结构中有指向其所属的进程指针task
static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; __asm__( "move.l %%sp, %0 " "and.l %1, %0" : "=&d"(ti) : "di" (~(THREAD_SIZE-1)) ); return ti; }
代码比较简单,获取sp寄存器的值,然后和~(THREAD_SIZE-1)相与就得到指向thread_info的指针。原理为何呢?我们都知道每个进程有用一个内核栈,当进程通过某种方式比如系统调用进入内核,需要把栈空间切换到内核栈。默认情况下,内核栈的大小是2个页面,也就是8KB。在栈的顶部保存着thread_info结构,基于栈是从高地址往低地址生长的,所以thread_info就是位于8KB地址区间的起始位置。例如内核栈空间为0xc9563000~0xc9565000(仅仅做示例,不代表任何实际意义),那么架构图如下所示:
如图所示,内核栈中,ESP指向任何时候必定位于0xc9563000~0xc9565000之间,所以此时我们可以看做是内核栈是8KB对齐的,既然如此回想下虚拟页面中如何获取虚拟页框基地址呢?正是把内部偏移位全都置0,然后和地址想与。so~这里也是如此,THREAD_SIZE-1就是栈内偏移位,取反就把除了偏移部分,其余部分全都置1,想与后无论如何结果始终指向内核栈区间的起始位置,图中为例就是0xc9563000.that's all,thank you!!
感谢主!
参考:
Linux内核3.10.1源码