IO模型
2020-09-28 15:55:42 2 举报
AI智能生成
登录查看完整内容
操作系统几种常见IO模型
作者其他创作
大纲/内容
I/O模型
BIO(Blocking IO)
应用程序中进程在发起IO调用后至内核执行IO操作返回结果之前,若发起系统调用的线程一直处于等待状态,则此次IO操作为阻塞IO。阻塞IO简称BIO,Blocking IO。其处理流程如下图所示:
问题:如果内核数据需要耗时很久才能准备好,那么用户进程将被阻塞,浪费性能。为了提升应用的性能,虽然可以通过多线程来提升性能,但线程的创建依然会借助系统调用,同时多线程会导致频繁的线程上下文的切换,同样会影响性能。所以要想解决BIO带来的问题,我们就得看到问题的本质,那就是阻塞二字。
NIO(Non-Blocking IO)
将阻塞变为非阻塞,那就是用户进程在发起系统调用时指定为非阻塞,内核接收到请求后,就会立即返回,然后用户进程通过轮询的方式来拉取处理结果。也就是如下图所示:
问题:非阻塞IO虽然相对于阻塞IO大幅提升了性能,但依旧不是完美的解决方案,其依然存在性能问题,也就是频繁的轮询导致频繁的系统调用,会耗费大量的CPU资源。比如当并发很高时,假设有1000个并发,那么单位时间循环内将会有1000次系统调用去轮询执行结果,而实际上可能只有2个请求结果执行完毕,这就会有998次无效的系统调用,造成严重的性能浪费。有问题就要解决,那NIO问题的本质就是频繁轮询导致的无效系统调用。
IO多路复用
select/poll
Select是内核提供的系统调用,它支持一次查询多个系统调用的可用状态,当任意一个结果状态可用时就会返回,用户进程再发起一次系统调用进行数据读取。换句话说,就是NIO中N次的系统调用,借助Select,只需要发起一次系统调用就够了(监听多个fd)。其IO流程如下所示
缺点:1、select底层采用数组实现,存在连接数限制,因此poll应运而生,其底层采用链表实现,与select相比,主要解决了连接限制2、select/epoll 虽然解决了NIO重复无效系统调用用的问题,但同时又引入了新的问题。问题是: 2.1、用户空间和内核空间之间,大量的数据拷贝 2.2、内核循环遍历IO状态,浪费CPU时间换句话说,select/poll虽然减少了用户进程的发起的系统调用,但内核的工作量只增不减。在高并发的情况下,内核的性能问题依旧。所以select/poll的问题本质是:内核存在无效的循环遍历。
epoll
针对select/pool引入的问题,我们把解决问题的思路转回到内核上,如何减少内核重复无效的循环遍历呢?变主动为被动,基于事件驱动来实现。其流程图如下所示:
epoll相较于select/poll,多了两次系统调用,其中epoll_create建立与内核的连接,epoll_ctl注册事件,epoll_wait阻塞用户进程,等待IO事件。
缺点:epoll,已经大大优化了IO的执行效率,但在IO执行的第一阶段:数据准备阶段都还是被阻塞的。所以这是一个可以继续优化的点。
对比
定义
I/O之于应用程序来说,强调的通过向内核发起系统调用完成对I/O的间接访问。换句话说应用程序发起的一次IO操作实际包含两个阶段:1、IO调用阶段:应用程序进程向内核发起系统调用2、IO执行阶段:内核执行IO操作并返回 2.1. 准备数据阶段:内核等待I/O设备准备好数据 2.2. 拷贝数据阶段:将数据从内核缓冲区拷贝到用户空间缓冲区怎么理解准备数据阶段呢?对于写请求:等待系统调用的完整请求数据,并写入内核缓冲区;对于读请求:等待系统调用的完整请求数据;(若请求数据不存在于内核缓冲区)则将外围设备的数据读入到内核缓冲区。
信号驱动IO(SIGIO)
信号驱动IO与BIO和NIO最大的区别就在于,在IO执行的数据准备阶段,不会阻塞用户进程。如下图所示:当用户进程需要等待数据的时候,会向内核发送一个信号,告诉内核我要什么数据,然后用户进程就继续做别的事情去了,而当内核中的数据准备好之后,内核立马发给用户进程一个信号,说”数据准备好了,快来查收“,用户进程收到信号之后,立马调用recvfrom,去查收数据。
缺点:乍一看,信号驱动式I/O模型有种异步操作的感觉,但是在IO执行的第二阶段,也就是将数据从内核空间复制到用户空间这个阶段,用户进程还是被阻塞的。综上,你会发现,不管是BIO还是NIO还是SIGIO,它们最终都会被阻塞在IO执行的第二阶段。那如果能将IO执行的第二阶段变成非阻塞,那就完美了。
异步IO(AIO)
异步IO真正实现了IO全流程的非阻塞。用户进程发出系统调用后立即返回,内核等待数据准备完成,然后将数据拷贝到用户进程缓冲区,然后发送信号告诉用户进程IO操作执行完毕(与SIGIO相比,一个是发送信号告诉用户进程数据准备完毕,一个是IO执行完毕)。其流程如下:
所以,之所以称为异步IO,取决于IO执行的第二阶段是否阻塞。因此前面讲的BIO,NIO和SIGIO均为同步IO。
总结
0 条评论
回复 删除
下一页