内核态用户态的数据拷贝,有点不明白

2020-07-04 15:13:39 +08:00
 yangyuhan12138

我们读一个文件的时候是需要系统调用的,也就是从用户态切换到内核态,然后内核态读取数据,再将数据拷贝到用户态,这中间的拷贝到底是个什么过程,内存里我们读取的这个文件的数据到底有几份,我觉得应该是一份,内核态拷贝到用户态应该只是把这份文件的地址给了用户态,不知道我理解的有没有问题...

7218 次点击
所在节点    程序员
47 条回复
no1xsyzy
2020-07-05 18:00:53 +08:00
物理地址是不暴露给用户的,你就算拿到也基本不能用。
因为内核访问用户空间方便,用户态访问内核空间要更麻烦地精细控制。所以 read 是用户提供一个(比如通过 mallocate 申请之后)分配到的地址空间,然后通知内核存进去。至于如何存,存完内核是否仍然保留,这是内核具体实现决定的。一次 call 至多存多少,存到哪是用户 call 参数决定的。
因此文件内存映射是一种优化,把文件读到内核,然后把某些地址空间设置为映射,对其的访问翻译为对已读取的文件的访问。这其中没有内存整片复制过程。

内存不会被直接访问,由内核来控制访问。分“页”来标记。用户空间内访问地址会被翻译为具体的真实内存地址(内核控制,CPU 实际操作)。甚至用户空间存在的页不一定真实有一个对应的内存,待到访问的时候触发缺页中断,再去问内核这块该是啥。

@Jooooooooo #37 指针内存储了 ✔ 指针存储了 ✘
指针内 一般就是指指针指向的地址空间。大概。
ltoddy
2020-07-05 18:31:07 +08:00
首先应该解释为什么有内核态,和用户态。内核态可以操作比如硬件,我们不想把这些危险的操作直接暴露给用户,而是封装起来给用户。内核态与用户态分别实现,当用户态的程序挂了之后,内核态不受影响,我们的操作系统照样运行的好好的。
那么这时候,自己思考一下,为什么要拷贝,如果不拷贝,会怎么样。
aheadlead
2020-07-05 20:35:54 +08:00
xyjincan
2020-07-06 09:41:34 +08:00
用户态的东西,用户有读写权限,内核态可能用户只有读权限,如果用户态只读一个内核地址,那不是可以直接绕过内核态修改来了
lyi4ng
2020-07-06 12:06:25 +08:00
这些东西都要考虑发展史的,内核态用户态的设计是一种非对称访问机制,这主要是为了安全考虑,即将仅有的一块内存划分成两部分区分出权限来,这是迎合 CPU 的特权级,因此实际上来说按照 CPU 特权级才有用户态内核态一说,而按照内存空间划分叫做内核空间 /用户空间。你再想一个事情,32 位 CPU 寻址能力是 4G,那我差了 8G 内存条怎么说?就光说内核态要求能访问到所有的内存单元,你知道实现方式吗?高端内存因为 CPU 的寻址能力发展直接在 64 位里被淘汰了,然后再说你想的虚拟地址物理地址,内核空间里也有虚拟地址,只不过和物理地址的关系上不像用户空间那样复杂,而用户空间大家告诉你是分页,那为什么就要分页?为什么要四级分页?一级二级不行吗?一级二级分页都是出现过的,但是因为计算机的发展又慢慢被淘汰了,多看背景再学机制,因为 kernel 的那群人大部分都很骄傲,如果没有需求驱动或者不是灵光一闪的话,你以为他们真的会改进代码,笑话,当年 COW 出脏牛的时候 linus 还不是发邮件喷人了。
(来自于因为大雨而迟到的发泄,语气过激请见谅)
xeaglex
2020-07-06 12:59:56 +08:00
@ichao1214 你要是觉得直接看 DMA 看不明白,那就去看[零拷贝技术]。不信你看完还不懂
yannxia
2020-07-06 13:43:51 +08:00
不明白很正常……
讲道理按照逻辑说,的确是应该将 地址直接从内核态作为返回值直接给用户态就可以了。但是在实际上因为安全 /硬件 还有一些历史原因导致,最基础的传递是通过 Copy 来的,之后才出现的 Zero Copy 的技术。

OS 因为要配合硬件,所以不是一个很纯粹的软件设计思想,这个只能按照他的思路来。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/687113

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX