I/O模型-读书笔记
I/O模型:
I/O操作需要内核系统调用来完成,系统调用需要Cpu来调度,而Cpu的访问速度相对于I/O来说比较快,所以Cpu不得不浪费Cpu时间来等待慢速I/O操作.
通过多进程方式来充分利用CPU资源,当还是希望让Cpu花费少的时间在I/O操作的调度上,这样就可以有更多的Cpu来完成I/O操作.
很多技术和策略都围绕如何让高速的Cpu和慢速的I/O设备更好的协调工作.
I/O操作主要是网络数据的接收和发送,以及磁盘文件的访问.归纳为多种模型称为I/O模型,本质区别在于Cpu的参与方式.
PIO和DMA:
慢速I/O设备和内存之间传输方式
PIO:磁盘和内存之间的数据传输需要Cpu控制,读取磁盘文件到内存的时候,数据需要经过Cpu存储转发.
DMA:可以不经过Cpu而直接进行磁盘和内存的数据交换,DMA模式下,Cpu只要向DMA控制器下达指令,让DMA控制器来处理数据的传输即可.DMA控制器通过系统总线来传输数据,传输
完毕后再通知Cpu.这样减低了Cpu占有率.
同步阻塞I/O:
I/O等待例子很多,比如web服务器等待用户请求.比如服务器与浏览器建立TCP链接后,需要等待用户发送HTTP请求.
I/O等待不可避免,有等待就会有阻塞.阻塞指的是当前发起I/O操作的进程被阻塞,并不是Cpu被阻塞,实际上没有什么能让Cpu阻塞,它只知道干活.
同步阻塞I/O指当前进程调用I/O操作的系统调用或者库函数时候,比如accept,send,recv等,进程便暂停,等待I/O操作完成后再继续运行.这样的I/O模型可以和多进程结合有效利用Cpu资源.
同步非阻塞I/O:
在同步阻塞I/O中,进程实际上等待的时间包括二部分,一个是等待数据的就绪,另外一个是等待数据的复制.对于网络I/O来说,前者的时间可能更长.
同步非阻塞I/O的调用不会等待数据的就绪,如果数据不可读写,则立即告诉进程.这种非阻塞I/O结合反复轮询来尝试数据是否就绪,防止进程被阻塞.最大的好处便在于可以在同一个进程里
同时处理多个I/O操作.但是由于一直在多次轮询查看数据是否就绪,花费大量Cpu时间.非阻塞I/O一般只针对网络I/O有效,对于磁盘I/O非阻塞I/O不产生效果.
多路I/O就绪通知:
web服务器同时处理大量文件描述符必不可少.由于要对socket检查是否可以接收的数据,则会浪费太多的Cpu时间.
多路I/O就绪通知出现,提供了对文件描述符就绪检查的高性能方案.允许进程通过一种方法来同时监视所有文件描述符.并可以快速获得所有就绪的文件描述符.然后只针对这些描述符进行数据访问.
I/O就绪通知只是帮助快速获得就绪的文件描述符.当得知数据就绪后,就访问数据本身而言.仍然需要选择阻塞和非阻塞的访问方式.多路I/O就绪通知有多种实现.
select:
通过一个select系统调用来监视包含多个文件描述符的数组.当select返回后,该数组中就绪的文件描述符会被内核修改标志位.使得进程可以获得这些文件描述符从而进行读写操作.
select的缺点
1)单个进程能够监视的文件描述符的数量存在最大限制.
2)select维护的存储大量文件描述符的数据结构,随着文件描述符量的增大,复制的开销也线性增长.
3)网络响应时间的延迟使得大量Tcp链接处于非活跃状态,但是select会对所有socket进行一次性扫描,也浪费了一定开销.
poll:
没有最大文件描述符的限制.select和poll将就绪的文件描述符告诉进程后,如果进程没有对其进行I/O操作,下次调用select和poll的时候将再次报告这件文件描述符.所以不会丢失就绪的
消息,该方式称为水平触发.
sigio:
sigio不是每次都告诉我们文件描述符是否就绪,而是高速文件描述符刚刚变为就绪,只说一次,称呼为边缘触发.
/dev/poll:
使用虚拟的/dev/poll设备,可以将有监视的文件描述符数组写入这个设备,然后通过ioctl来等待时间通知.没有提供直接的内核支持,所以性能不是很稳定.
/dev/epoll:
在/dev/epool的基础上增加了内存映射.
epoll:
本质的改进是epoll基于事件的就绪通知,通过callback的机制来激活文件描述符.
内存映射:
linux内核提供一种访问文件的特殊方式.可以将内存中某块地址空间和制定的磁盘文件相关联.从而对这块内存的访问转换为对磁盘文件的访问.
大部分情况下,使用内存映射可以提高磁盘I/O访问的性能,因为无须read或者write系统调用,而是通过mmap系统调用建立内存和磁盘文件的关联,然后像访问内存一样只有访问文件.
直接I/O:
linux2.6中,内存映射和直接访问文件没有本质区别.因为数据从进程用户态内存空间到磁盘需要经过二次复制,及在磁盘与内核缓存区之间以及在内核缓存区与用户态内存空间.
引入内核缓存区的目的在于提高磁盘文件的访问性能.比如进程读取磁盘文件的时,如果文件已经在内核缓冲区中,那么就无须再访问磁盘.而进程需要向文件中写入数据的时候.则
直接写到内核缓存区便告诉进程已经成功写入,写入磁盘是通过一定策略进行延迟.
为了充分提高性能,系统绕过内核缓存区,由自己在用户空间实现管理I/O缓存区,比如数据库的缓存机制和写延迟机制.
Linux提供了对这种需求的支持,在open系统调用的时候增加参数选项O_DIRECT.用它打开的文件便可以通过内核缓存区的直接访问,有效避免了Cpu和内存的多余时间开销.
Sendfile:
引入Sendfile在于内核希望请求的处理尽量在内核完成,减少内核态的切换以及用户数据复制的开销,Linux通过系统调用提高这种机制,它可以将磁盘文件的特定部分直接传送到客户端的Socket
描述符,所以一般使用在网卡传输,减少cpu和内存的开销.
异步I/O:
同步和异步,阻塞和非阻塞容易被混用,其实完全不一样,修饰的对象也不同.
建议继续学习:
- 关于IO的同步,异步,阻塞,非阻塞 (阅读:14552)
- Linux服务器性能评估 (阅读:8302)
- 提升磁盘IO性能的几个技巧 (阅读:7617)
- Innodb IO优化-配置优化 (阅读:6755)
- 查看 CPU, Memory, I/O and NetFlow (阅读:6530)
- blktrace 深度了解linux系统的IO运作 (阅读:6026)
- Linux操作系统内核3.3版本I/O Stack的流图 (阅读:5794)
- Linux IO协议栈框图 (阅读:5405)
- MySQL Tuning之浅析I/O优化 (阅读:5196)
- Linux下的一些I/O统计工具 (阅读:4929)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:ywdblog 来源: 技术 总结 记录 生活 工作
- 标签: IO
- 发布时间:2011-02-22 07:35:40
- [70] Twitter/微博客的学习摘要
- [65] find命令的一点注意事项
- [64] 如何拿下简短的域名
- [64] IOS安全–浅谈关于IOS加固的几种方法
- [63] android 开发入门
- [62] 流程管理与用户研究
- [62] Go Reflect 性能
- [60] Oracle MTS模式下 进程地址与会话信
- [59] 图书馆的世界纪录
- [58] 读书笔记-壹百度:百度十年千倍的29条法则