- 论坛徽章:
- 0
|
本帖最后由 l4rmbr 于 2013-05-10 15:48 编辑
z32556601 发表于 2013-05-10 14:46 ![]()
但上面的图显示的内核栈的地址空间,为什么地址小于0xc0000000
回复 4# l4rmbr
从内核态地址开始(也就是PAGE_OFFSET), 到VMALLOC_START 的线形地址空间直接映射到物理内存空间
(一一对应,物理地址=线形地址-PAGE_OFFSET), 所以, esp 虽然指向线性地址, 但实际物理地址是要
减去PAGE_OFFSET, 这个值 在x86上是典型的3G. 这也就是为什么你图中的地址值那么小的原因. 它是个物理
地址. 但esp的值是个线性地址, 个人觉得这图有误导人认为此时esp里的值就是这个物理地址的嫌疑.
这个esp只是cpu指令认识的值, 它最终还要经过mmu转换为实际物理地址.
-------------------------------------------------------------------------
另外,请接着看.
current是一个用来指向当前进程task_struct指针的宏.
它的计算方式很取巧 , 就是取当前进程内核栈的栈顶指针(esp)与栈大小-1相与.
为什么这么做?
thread_info结构第一个元素就是指向当前进程task_struct的指针, 换言之,
只要取得thread_info的地址, task_struct地址也就可以获得了.
而thread_info又恰好是跟内核栈在一起, 看代码(include/linux/sched.h)
union thread_union {
struct thread_info thread_info;
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
thread_info 刚好跟内核栈在一个union里面. 占THREAD_SIZE大小(典型的值是8k, 两页, x86上)
要注意的是, thread_info处在最低地址, 而stack则从最高地址往下生长(所以, stack其实没有8k大,
要不它会把thread_info结构覆盖掉, 看你的配图应该就很直观地明白我说的什么意思).
所以, 用栈顶指针, 跟THRED_SIZE-1进行与操作, 它的效果就是把与THREAD_SIZE对齐的值屏蔽掉,
就是获得了这个内核栈最低的值, 这个值刚好就是thread_info的地址.
|
|