I/O缓冲
#defineBUFFERSIZE 4096
charbuf[BUFFERSIZE];
read(fd, buf, BUFFERSIZE);
write(fd, buf, BUFFERSIZE);
这里调用read从描述符fd中读取数据, BUFFERSIZE定义了每次每次读/写的数据长度,这里的
值是4096。该缓冲区的大小对性能将会产生很大影响。
例如:对一个2500字节的文件copy操作
缓冲区大小 | read和write次数 |
100字节 | 25次r、w |
1000字节 | 3次r、w |
原因:
用户进程位于用户空间,内核位于系统空间,磁盘只能被内核直接访问。程序读取磁盘上的数据只能通过系统调用read,而read的代码在内核中,所以当read调用发生时,执行权会从用户代码转移到内核代码,执行内核代码时需要时间的。
系统调用的开销大不仅仅是因为要传输数据,当运行内核代码时, CPU工作在管理员模式,这对应于一些特殊的堆栈和内存环境,必须在系统调用发生时建立好。系统调用结束后(read返回), CPU切换回到用户模式,必须把堆栈和内存环境恢复成用户程序运行时状态。
当工作在管理员模式下,程序可以直接访问磁盘、终端、打印机设备,还可以访问全部的内存空间。而在用户模式,程序不能直接访问设备,也只能访问特定部分的内存空间。在运行时刻,系统会根据需要不断地在两种模式间切换。
总结
当CPU把太多的时间消耗在执行内核代码和模式切换上,就不能有很多时间来执行程序中业务逻辑的代码或提供系统服务。所以要尽可能的减少模式间切换。对系统来说,这种时间上的开销是昂贵的。
应用缓存技术对提高系统的效率是很明显的,它的主要思想是一次读入大量的数据放入缓冲区,需要时从缓冲区取得数据。而不是每次需要数据都直接调用read。
内核缓存
背景:
管理员模式和用户模式之间的切换需要消耗时间,相比之下,磁盘的I/O操作消耗的时间更多,为了提高效率,内核也使用缓冲技术来提高对磁盘的访问速度。
实现:
磁盘是数据块的集合,内核会对磁盘上的数据块做缓冲。内核将磁盘上的数据块复制到内核缓冲区中,当一个用户空间中的进程要从磁盘上读取数据时,内核一般不直接读磁盘,而是将内核缓冲区中的数据复制到进程的缓冲区。当进程所要求的数据块不在内核缓冲区时,内核会把相应的数据块加入到请求数据列表中,然后把该进程挂起,接着为其他进程服务。
一段时间之后(很短),内核把相应的数据块从磁盘读到内核缓冲区,然后再把数据复制到进程的缓冲区中,然后唤醒被挂起的进程。
理解内核缓冲技术的原理有助于更好地掌握系统调用:read和write,read把数据从内核缓冲区复制到进程缓冲区,write把数据从进程缓冲区复制到内核缓冲区,它们并不等价于数据在内核缓冲和磁盘之间的交换。
从理论上讲,内核可以在任何时候写磁盘,但并不是所有的write操作都会导致内核的写动作。内核会把要写的数据析时存在缓冲区中.积累到一定数量后再一次写人。有时会导致意外情况,比如突然断电,内核还来不及把内核缓冲区中的数据写到磁盘上,这些更新的数据就会丢失。
总结:
应用内核缓冲技术导致的结果,提高磁盘I/O效率、优化磁盘的写操作、需要及时地将缓冲数据写入磁盘。当操作磁盘文件时,对其write操作之后,调用fflush将缓冲数据写入磁盘,以防止数据的以外丢失