开放系统调用的工作

时间:2012-10-07 11:20:37

标签: file file-io operating-system memory-mapped-files

我正在阅读有关内存映射文件的消息,该消息称它比传统方法更快地打开文件或读取文件,例如开放系统调用和读取系统调用,而不给出如何打开或读取系统调用的描述的工作原理。

所以这是我的问题开放系统调用的工作原理?

据我所知,它会将文件加载到内存中,而使用映射文件只会将其地址保存在内存中,并在需要时将所请求的页面放入内存中。

我希望澄清我迄今为止的理解。

修改

我之前的理解几乎是错误的,因为正确的解释是指Pawel接受的答案。

3 个答案:

答案 0 :(得分:6)

由于您没有提供任何细节,我假设您对类Unix系统的行为感兴趣。

实际上open()系统调用只会创建一个文件描述符,然后mmap()read()可以使用该文件描述符。

内存映射I / O和标准I / O都通过页面缓存在内部访问磁盘上的文件,这是一个缓存文件的缓冲区,以减少I / O操作的数量。

标准I / O方法(使用write()read())涉及执行系统调用,然后将数据从(或写入时)页面缓存复制到应用程序选择的缓冲区。除此之外,非顺序访问还需要另一个系统调用lseek()。系统调用很昂贵,复制数据也是如此。

当文件通过内存映射时,通常将进程地址空间中的内存区域直接映射到页面缓存,以便可以执行已加载数据的所有读取和写入,而无需任何额外延迟(无系统调用,无数据复制) 。仅当应用程序尝试访问尚未加载的文件区域时,才会发生页面错误,并且内核从磁盘加载所需的数据(整页)。

修改 我看到我还要解释记忆paging。在大多数现代架构中,存在物理内存,它是真正的硬件和虚拟内存,它为进程创建地址空间。内核决定虚拟内存中的地址如何映射到物理内存中的地址。最小的单位是一个记忆页面(通常,但不总是4K)。它不必是1:1映射,例如,所有虚拟内存页面都可以映射到相同的物理地址。

在内存映射的应用程序地址空间和内核页面缓存的I / O部分映射到相同的物理内存区域,因此程序可以直接访问页面缓存。

答案 1 :(得分:2)

Pawel精心解释了如何执行读/写操作。让我解释原始问题:fopen(3)如何工作: 当用户空间进程遇到fopen(在libc或任何用户空间库中定义)时,它会将其转换为open(2)系统调用。首先,它接受来自fopen的参数,将它们与open()系统调用号一起写入特定于体系结构的寄存器。这个数字告诉内核系统调用用户空间程序要运行。加载这些寄存器后,用户空间进程会中断内核(通过softirq,传统上是x86上的INT 80H)和阻塞。

内核验证提供的参数和访问权限等,然后返回错误或调用实际系统调用,在这种情况下为vfs_open()vfs_open()检查fd数组中的可用文件描述符并分配struct文件。访问文件的引用计数增加,fd返回给用户程序。这样就完成了open和大多数系统调用的工作。

open()read() / write()一起,后跟close()无疑是比缓冲区缓存中的内存映射文件更长的过程。

答案 2 :(得分:0)

有关Linux上的开放和阅读工作的清晰解释,您可以阅读this。代码片段来自内核的旧版本,但理论仍然存在。

您仍然需要使用open()系统调用来获取有效的文件描述符,您将传递给mmap()。至于为什么mmaped IO更快,这是因为没有(从)用户空间到(来自)内核空间缓冲区的数据副本,这是读写系统调用所发生的。