内存映射文件和传统的I/o过程的区别
传统IO:块设备文件,磁盘文件
系统调用->页高速缓存->分配新页->磁盘->页高速缓存->用户进程空间的缓冲区
系统调用
read(),write()
系统调用read()将阻塞调用进程,知道数据被拷贝进用户态地址空间。规范模式但wirte()不同,它在数据被拷贝到页高速缓存(延迟写)后马上结束。同步模式完全写入磁盘
内存映射模式:
mmap()将文件映射到内存中,文件就称为RAM中的一个字节数组,应用程序就可以直接访问数组元素,而不需用系统调用read(),write()或lseek()
可执行文件的加载
写页表->缺页异常->页高速缓存->新分配页->磁盘I/O->页高速缓存->更新页表项指向页高速缓存地址。
相关系统调用
以加载可执行文件的方式读文件,少了一次数据的拷贝。
页高速缓存:
内核缓冲区在linux下的实现:
历史:
旧版本页高速缓存和缓冲区高速缓存,前者用来存放访问磁盘文件内容时生成的磁盘数据项,后者把通过文件系统访问的块的内容保留在内存中。
后来,由于效率原因,不在单独分配块缓冲区,相反把它们存放在叫做“缓冲区页”的专门页中,而缓冲区页保存在页高速缓存中。
引用《深入理解linux内核》:
1.页高速缓存是Linux内核所使用的主要磁盘高速缓存,在绝大多数情况下,内核在读写磁盘时都应用页高速缓存。新页被追加到页高速缓存以满足用户态进程的读请求。如果页不在高速缓存中,新页就被加到高速缓存中,然后用从磁盘读出的数据填充它。
2.页高速缓存中的每个页所包换的数据肯定属于某个文件。这个文件(索引节点)就称为页的所有者。
3.几乎所有的文件读和写操作都依赖于页高速缓存。只有在O_DIRECT标志被置位而进程打开文件的情况下才会出现例外,此时I/O数据的传送绕过了页高速缓存而使用了进程用户态地址空间的缓冲区。