copy_from_user的疑惑

发布于 2022-10-15 04:11:21 字数 569 浏览 13 评论 0

copy_from_user是从内核空间读取用户空间的数据。
copy_from_user(void *to, const void __user *from, unsigned long n)
32位操作系统,from是用户空间的指针,地址小于0XC0000000,to是内核空间指针,地址大于0XC0000000。
我知道操作用户空间地址,应该都是要经过GDT把虚拟地址转化为线性地址(在Linux中,经过GDT转化后,其实虚拟地址就是线性地址),然后通过CR3寄存器(CR3里面的地址应该是物理地址吧,由内核来负责装入)找到页表,页目录,然后把线性地址最终转化为物理地址。
操作内核空间的地址不太清楚,是按照上面步骤,通过GDT,CR3得到物理地址还是通过__pa这个宏,直接减去0XC000000这个偏移得到物理地址的呢?
from是用户空间的指针,是虚拟地址(其实就是线性地址),应该在用户的数据段里,要读from地址的内容,应该把该用户数据段所在的页表地址放到CR3寄存器里,然后转化为物理地址进行读取吧。
我看了copy_from_user的源代码,源码里面好像没有操作CR3寄存器的语句,没搞懂它到底是怎么读取用户空间的数据,然后写到内核空间中去的?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

深爱不及久伴 2022-10-22 04:11:21

地址轉換全部都是由MMU完成的

国粹 2022-10-22 04:11:21

不管用户空间还是内核空间,逻辑地址到物理地址都是通过MMU(GDT,CR3)进行转化的。对于内核逻辑地址来说,通过MMU转化就相当于减去0xC0000000这个偏移地址,是这个意思吧?
copy_from_user是怎么读取用户空间的数据的呢?我看源代码最终就是调用mov语句实现的,它怎么知道用户空间地址是那个进程的?如果进行GDT,CR3这些转化的呢?

动听の歌 2022-10-22 04:11:21

本帖最后由 zhanglong71 于 2011-06-16 21:58 编辑

1.开启分页功能后,能直接访问的只是线性地址。机器(x86)的寻址过程是:
  逻辑地址---(分段单元)--->线性地址---(分页单元)--->物理地址
2."通过MMU转化就相当于减去0xC0000000这个偏移地址,是这个意思吧?"
  这样说是不合适的。
  内核线性地址减去0xC0000000得到物理地址,是因为在机器初始化页目录页表项数据时,将0-896MB的物理地址空间建立平板映射,也就是将0-896MB的物理地址空间映射到0xc0000000-0xc0000000+896MB的线性地址空间。并且这种关系只在此范围内才能成立。超出此范围的就不行了。
3.copy_from_user只能用在进程上下文中。
    在调度器切换任务并加载进程的执行环境时,会将其进程的task_strcut结构中的相关数据项分别加载到GDTR和CR3.也就是每个进程都有自己的GDTR和CR3.
    在调用copy_from_user时,其中的两个地址都可看成是线性地址。在访问此地址时,机器通过GDTR,CR3将其转换成物理地址后访问其中的数据,而这一转换过程是不可见的。

幸福还没到 2022-10-22 04:11:21

我来解释一下, 一个进程无论 内核还是用户空间都只有一个 页目录表, 内核调用copy_from_user的时候如果 内核映射页不存在就会发生异常,缺页异常中切换一下映射表,继续读取参数值。

一梦等七年七年为一梦 2022-10-22 04:11:21

根据大家的描述,是下面这个意思吧。
进程从用户态进入内核态不会引起CR3的变化。所有进程的内核空间都是一样的。
所有进程的页表中对应于线性地址范围为3g-4g的页目录是一致的,对应于内核空间,对应于相同的物理地址。对应于线性地址范围为0-3g之间的用户空间页目录不一致,对应不同的物理地址。
所有进程的页表中3g-4g的页目录都是相同的,这个是不是浪费了内存空间哈?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文