免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 2841 | 回复: 10
打印 上一主题 下一主题

[内核入门] esp [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-05-10 12:33 |只看该作者 |倒序浏览
本帖最后由 z32556601 于 2013-05-10 14:06 编辑

%esp中存放的线性地址还是物理地址...

论坛徽章:
0
2 [报告]
发表于 2013-05-10 12:47 |只看该作者
回复 1# z32556601
具体的分法应该是:逻辑地址->虚拟地址->物理地址,对于linux而言应该逻辑地址就是虚拟地址,所以从程序的角度看,程序都是用的虚拟地址,不论是内核还是用户程序。内核里面限制的0xc000_0000就是虚拟地址。虚拟地址通过MMU转换后变成物理地址。顺便回你另外一个帖子,没看到你提到的图,如果真是小于0xc000_0000的话,只能说图里给的是物理地址。


   

论坛徽章:
0
3 [报告]
发表于 2013-05-10 13:47 |只看该作者

上图,深入理解linux内核第三章进程.
回复 2# xs3c


   

论坛徽章:
0
4 [报告]
发表于 2013-05-10 14:42 |只看该作者
z32556601 发表于 2013-05-10 12:33
%esp中存放的线性地址还是物理地址...



Hi,  z32556601,

是线性地址.  由你引用的图其实也说明了, 这个图是一个进程的地址空间的布局图, 显然引用的地址是一个线性地址.
此外, esp作为x86上的栈顶指针, 是用来标示当前栈(用户态栈或核心态栈)的栈顶,  这是用户态程序或核心态程序用
以实现函数调用的. 那从这个意义上看, 它们认识的也是线性地址.所以, esp存放的是线性地址.

论坛徽章:
0
5 [报告]
发表于 2013-05-10 14:46 |只看该作者
但上面的图显示的内核栈的地址空间,为什么地址小于0xc0000000
回复 4# l4rmbr


   

论坛徽章:
0
6 [报告]
发表于 2013-05-10 15:34 |只看该作者
本帖最后由 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的地址.

论坛徽章:
0
7 [报告]
发表于 2013-05-10 15:45 |只看该作者
了解了.在汇编或所有程序看来%esp保存的是线性地址.但在真正的cpu里的%esp寄存器其实保存的是经过MMU转换后的物理地址,是这样吗
回复 6# l4rmbr


   

论坛徽章:
0
8 [报告]
发表于 2013-05-10 15:55 |只看该作者
本帖最后由 l4rmbr 于 2013-05-10 15:58 编辑
z32556601 发表于 2013-05-10 15:45
了解了.在汇编或所有程序看来%esp保存的是线性地址.但在真正的cpu里的%esp寄存器其实保存的是经过MMU转换 ...


我对答案做了些修改, 你再读读.

另外,  汇编级别的是线性地址. 回想, 在调试程序时, 直接查看这些寄存器的值是线性地址. 而不是实际对应物理内存单元的地址.

下面是x86典型的线性地址 -> 物理地址 的转化过程(忽略了一些无关的细节, 只涉及基本原理 ):

cpu发起读取这个地址(下称为VA)中存放的数据的指令时,  会触发mmu进行转换,  首先, 它从地址VA中抽取出页目录项, 然后, 从CR3寄存器中获取
全局偏移表(GDT)的物理地址,  把这个目录项当做下标,  获取在表中的某一项,  其中记载着下一级页表的物理地址, 然后再从VA抽取出页表项, 把它
当成下标, 与刚获得的页表物理地址相加, 获取最终那个物理页框的物理地址PA.  最后一步,  VA最后12位表示页内偏移,  再把这个页内偏移与PA相加
,得到你确切想要的物理地址, 然后从其中取出放在其中的数据.

论坛徽章:
0
9 [报告]
发表于 2013-05-10 16:03 |只看该作者
那就是esp里存的是线性地址.当cpu读到该值并寻址时会触发mmu经过转换后获得物理地址,再去取数据.这次对了吧.....
回复 8# l4rmbr


   

论坛徽章:
0
10 [报告]
发表于 2013-05-10 16:13 |只看该作者
z32556601 发表于 2013-05-10 16:03
那就是esp里存的是线性地址.当cpu读到该值并寻址时会触发mmu经过转换后获得物理地址,再去取数据.这次对了吧 ...



加个前提, 在保护模式下, 而不是在实模式下.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP