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

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

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

6994 次点击
所在节点    程序员
47 条回复
crclz
2020-07-04 15:20:36 +08:00
ssize_t read (int fd, void *buf, size_t count); 这是一个系统调用。拷贝就指的是将磁盘上的数据拷贝到 buf (第二个参数)的过程.
zhgg0
2020-07-04 15:22:19 +08:00
我的理解是将内核态的数据拷了一份到用户态,不是给地址。
zhgg0
2020-07-04 15:25:39 +08:00
接#2
假设有两个进程都要读某一个文件,A 先读,B 再读; A 读的时候操作系统把文件加载到内核态,把这个数据直接拷了一份给 A,B 再度,此时大概率操作系统还缓存了数据,再拷贝一份给 B ;如果直接给地址的话,不好处理 A 、B 同时修改内容,或者 A 和操作系统同时要修改内容这种情况。
billlee
2020-07-04 15:25:57 +08:00
不是的,真要拷贝,给地址的话那岂不是还要考虑内存回收问题
xeaglex
2020-07-04 15:27:10 +08:00
你先了解一下 DMA 的功能,剩下的你就全懂了
ZRS
2020-07-04 15:39:40 +08:00
就是真的在内存里复制一遍。。
reus
2020-07-04 15:44:09 +08:00
都说了拷贝了,怎么可能是给地址
但凡知道 read 调用的都不会问出这种问题
Jooooooooo
2020-07-04 15:55:03 +08:00
如果是地址的话, 你要真的访问数据得去磁盘上拿这得多慢啊

各种都是都是有缓存的, 网卡, 磁盘, 内存, cpu 全是 cache 在干活, cpu 真的要计算东西也是本地缓存跑, 每次都是内存拿东西要慢死
louettagfh
2020-07-04 17:26:09 +08:00
是真的拷贝一次啊

函数就是 copy_to_user()

unsigned long copy_to_user ( void __user * to,
const void * from,
unsigned long n);
louettagfh
2020-07-04 17:31:41 +08:00
接上一条 拷贝的原因是因为进程申请的 buf 都是用户空间的虚拟地址,就如你用 mmap 也是可以直接访问内核态的地址空间,这就省去了一次拷贝
DoctorCat
2020-07-04 19:40:05 +08:00
顶楼上,再补充一下:
1. 文件读取操作是需要用户态 和 内核态一起互动的,为啥?文件系统层 VFS 就这么设计的,可能是迄今为止最周到最稳固的设计。执行过程要考虑到方方面面,例如页缓存、文件于页映射、块缓存等等复杂的机制。
2. mmap 这个系统调用可以直接映射到可执行文件代码和只读数据。脱离了文件系统层( 见内核函数实现 do_mmap_gpoff )
zivyou
2020-07-04 23:45:37 +08:00
顶 @louettagfh 就是 copy_to_user()。至于读文件的过程,默认情况下内核会有个缓冲区
zmxnv123
2020-07-05 00:38:17 +08:00
文件系统是操作系统的一部分。对于硬盘中的每个 block 会对应内核中的一块相同大小的 buffer,从硬盘拷贝到内核的 buffer 是第一次拷贝,发生在内核态,之后要把内核 buffer 中的内容拷贝到用户态的 buffer 。
vk42
2020-07-05 00:42:40 +08:00
@louettagfh mmap 也是用户空间,并不会直接访问内核地址空间……
janxin
2020-07-05 07:28:13 +08:00
Linux 新内核的机制 io_uring 就是提升这个性能的,具体可以看一下相关介绍里也有提到
ichao1214
2020-07-05 09:10:02 +08:00
@xeaglex 请解答一下,看其他回答好像没有提到 dma
louettagfh
2020-07-05 09:59:51 +08:00
@vk42 自己看源码吧 懒得解释了
vk42
2020-07-05 10:33:53 +08:00
@louettagfh 你确定你能搞清虚拟地址空间和物理地址区别? mmap 可以把 page cache 映射到进程的用户态空间以实现 zero copy,但这不是访问内核态地址空间好么
louettagfh
2020-07-05 10:40:55 +08:00
@vk42 vma 映射的不是内核地址空间? 访问 vma 不是访问内核地址空间?
vk42
2020-07-05 10:48:04 +08:00
@louettagfh
你去查一下内核地址空间的定义再说吧(我怀疑你把物理地址理解成所谓的内核地址空间了)
另外 vma 并不是真正映射的地方,vma 只是对地址空间做 book keeping,真正的映射是 page table 的活。

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

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

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

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

© 2021 V2EX