1.通过thread_union,使进程内核态堆栈和thread_info紧密结合在一起。
文件include/linux/sched.h当中,有thread_union的定义
2.esp指向的是内核堆栈的结尾,由于堆栈是向下增长的,esp和thread_info位于同一个8KB或者4KB的块当中。
也就是thread_union的长度了。如果是8KB,屏蔽esp的低13位就可以得到thread_info的地址,也就是8KB块
的开始位置。4KB的话,就屏蔽低12位。
在文件include/asm-x86/thread_info_32.h当中我们可以看到current_thread_info()函数调用是如何实现的。
直接返回thread_info指针,当前的堆栈指针current_stack_pointer,也就是esp,THREAD_SIZE为块的字节大小
8192或者是4096,这里假设值8192,十六进制的表示是0x00002000,二进制的表示是00000000000000000010000000000000
~(THREAD_SIZE-1)的结果刚好为1111111111111111111 0000000000000,第十三位是全为零,也就是刚好屏蔽了esp的低十三位,最终得到的是thread_info的地址。
可以用汇编语言描述,更加直观:
最后p中就包含了,thread_info的地址了。
3.获取进程描述符的地址
我们先看看thread_info这个结构的具体定义,在文件中。
要获取进程描述符,也就是task指针,上面可以看到,其在thread_info结构当中的偏移量刚好是0,所以上面也就是获得了task指针,也就是进程描述符的指针。