在IO处理中有2种思路,一种就是轮训(polling)机制,一种是中断(interrupt)机制,前置是一种同步的通信机制,不是计算机中IO采用的机制,我们重点来说明中断机制。
CPU停下当前的工作任务,去处理其他事情,处理完后回来继续执行刚才的任务,这一过程便是中断。中断分为外部中断和内部中断。
外部中断
内部中断
在现代计算机中,进行磁盘IO或者网络IO的时候,CPU是不会全程参与的,CPU只会下发数据传输的指令,比如是读还是写,设备类型还有内存地址等发送给设备的设备控制器,后续会由设备和内存直接进行数据传输,这样就能节省CPU昂贵的开销,这就是DMA机制。
DMA的主要成就是将耗时较久的数据IO时间直接交由内存和设备来做,不太需要CPU的参与,让CPU去做更有价值的事情。
没有DMA之前:
DMA解决CPU数据拷贝阻塞的问题:
总结:DMA相当于在CPU和IO设备间加入了一个中间层,之前他们直接交互,现在DMA等数据传输好了再通知CPU。
传统的数据拷贝过程中,数据需要从内核缓冲区复制到用户空间缓冲区,然后再从用户空间缓冲区复制到内核缓冲区,这个过程会耗费大量的CPU时间和内存带宽,降低系统的性能和吞吐量。
为了解决这个问题,零拷贝技术应运而生。零拷贝技术是指在数据传输过程中,尽量避免将数据从一块内存拷贝到另一块内存,从而减少了CPU的开销和内存带宽的消耗,提高了系统的性能。
未应用零拷贝技术之前:
传统的IO拷贝技术,会有4次数据拷贝,2次系统调用,4次上下文切换,但是由于内核态到用户态的数据拷贝不涉及数据的运算,所以理论上不需要拷贝到用户态;
目前有2中常见的零拷贝技术:(1)mmap+write;(2)sendfile;
通过mmap技术,解决用户态无法访问内核态数据的的问题,能够直接在内核态进行数据的拷贝,这样就减少了在用户态进行CPU拷贝的过程;
对于mmap技术,还是会有2次系统调用,造成4次上下文切换。
现在引入sendfile调用,直接是将缓存区的描述符传递给socket缓存的描述符,直接替换read和write调用,这样只需要一次系统调用,2次上下文中断;
IO多路复用技术是指这样一个过程:
过程中描述的函数在Linux中select、poll、epoll实现。
将所有连接的socket文件描述符放置到文件描述符集合中,通过select函数将其复制到内核态空间,检查其网络事件,该检查是通过轮训的方式,并且该描述符集合是顺序表保存。所以保存的文件描述符有限。
select是一种轮训机制,会去轮训文件状态描述符,缺点是轮训对象有限,64位的Linux系统也只能是2048个;将已经连接的socket文件描述符放置到数组中,再将该数组拷贝到内核空间中做检查,看哪些socket是在read还是write状态,然后对其进行处理。
poll看起来和select实现的机制差不多,只是没有了socket连接数量的限制,这是由于他是用链表来保存socket文件描述符;
epoll是基于OS的事件通知机制,socket事件发生了会将事件通知到工作线程处理;
总结:select和poll的实现都是监听对象轮训文件描述符集合中事件,select中文件描述符集合有限,poll中文件描述符集合理论上上无限,但其工作线程其实是阻塞的,就是一直在等待他们将事件报送过来在进行处理。
epoll是基于事件机制来实现,其实现是在对每个文件描述符后都记录其对应的工作线程信息,但监听到事件就能直接通知工作线程来工作。
本文由博客一文多发平台 OpenWrite 发布!