当前位置: 首页 > news >正文

阻塞IO与非阻塞IO

一、阻塞IO/非阻塞IO 与 进程

进程有三个基本状态,运行态就绪态阻塞态(睡眠态)
所谓阻塞式IO,就是进程等待IO时会进入阻塞态,让出CPU。

在这里插入图片描述

对于一个想要进行IO操作的进程来说,可以选择阻塞IO非阻塞IO两种方式。如果选择阻塞IO,在等待IO时进程就会进入阻塞态,进程也就不会在CPU上继续运行了,可以让出CPU,使CPU可以切换到其他进程运行;如果选择非阻塞IO,就不会一直等待IO,也就不会进入阻塞态,继而可以继续在CPU上运行,这样在等待IO时发起其他IO或处理已经完成的IO。

二、阻塞IO与非阻塞IO

文件IO是否为阻塞式IO,取决于用open()函数以什么方式打开。

2.1 阻塞IO

open()函数默认阻塞IO的方式打开文件,也就是进程默认在等待IO时会进入阻塞态,不会继续在CPU上运行。

int fd;
char buffer;
fd = open("/dev/sda", O_RDWR);
ret = read(fd, &buffer, sizeof(buffer));

2.2 非阻塞IO

open()函数可以通过添加非阻塞标志位O_NONBLOCK,以非阻塞IO的方式打开文件。

int fd;
int buffer;
fd = open("/dev/sda", O_RDWR | O_NONBLOCK);
ret = read(fd, &buffer, sizeof(buffer));

应用程序通过poll()、epoll()和select()三个函数来轮询设备是否可用,从而实现非阻塞IO。

2.2.1 select()函数

select()函数把想要读的文件放到一个集合里,把想要写的文件放到一个集合里,把需要监测异常的文件也放到一个集合里,然后再设置一个超时时间。在超时时间内,如果这三个集合里出现了可用的文件,select()就返回一个大于0的数表明可用。

在这里插入图片描述

select()通过宏定义 FD_XXX 来往监测文件集合里增加、删除文件。

void FD_ZERO(fd_set *set) 			// 把文件集合清空
void FD_SET(int fd, fd_set *set) 	// 往集合里加入一个文件
void FD_CLR(int fd, fd_set *set) 	// 从集合里删除一个文件
int FD_ISSET(int fd, fd_set *set)	// 判断一个文件在不在这个集合里

select()默认最多能够监视1024个文件。

2.2.2 poll()函数

poll()函数对于监视时间的数量没有限制。
select()函数是将监视文件按读、写、异常分类监视,而poll()函数把所有文件放到一个集合里,然后设置每个文件要监视的属性。

在这里插入图片描述

2.2.3 epoll()函数

select()和poll()都会随着文件数量的增加,效率变低,为了解决高并发问题发明了epoll()函数,一般在大规模并发服务器网络编程中使用。

因此,一般使用select()和poll()函数来做非阻塞IO。

三、阻塞IO与非阻塞IO的底层实现原理

3.1 阻塞IO的底层实现原理

要想实现阻塞IO,就需要编写对应设备文件的驱动来实现阻塞IO。

  • 阻塞IO的实现方式:等待队列

等待队列是Linux内核提供的一种可以实现阻塞IO的方式。等待队列通过把想要访问该设备文件的进程1、进程2、进程3放入一个队列里排队等待;等到设备可以使用时,就可以依次唤醒等待队列里的进程1、进程2、进程3;阻塞态的进程是通过中断唤醒的,所以进程一定设置成TASK_INTERRUPTIBLE状态。

在这里插入图片描述

3.2 非阻塞IO的底层实现原理

应用程序通过poll()、epoll()和select()三个函数来轮询设备是否可用,对应的都是设备文件驱动的poll()函数。

  • 非阻塞IO的实现方式:poll()函数轮询
    在这里插入图片描述

四、阻塞IO和非阻塞IO的特点总结

采用阻塞IO还是非阻塞IO主要取决于,进程切换成本CPU轮询成本 哪个更小!

阻塞IO会让出CPU,可以让给其他进程执行,所以适合连接数少、间隔较长时间才可用的设备。比如,按键驱动,只有用户按下时才会有效,非阻塞IO需要一直轮询,CPU占用率极高,而阻塞IO可以很好地解决这种情况;

非阻塞IO会继续占用CPU,进程处于忙等待,但可以让给其他线程执行,所以适合连接数多(高并发)、间隔时间较短就可用的设备。比如,DMA数据采集,完成DMA数据采集不需要很长时间,因此隔一小段时间就会可用,所以阻塞IO切换进程会很耗时,而非阻塞IO可以很好地解决这种情况。

总结,进程进行阻塞IO会进入睡眠态,IO完成后会被唤醒,底层采用等待队列实现,非阻塞IO适合连接数少的情况;
进程进行非阻塞IO,会不断轮询所有监测文件集合里的文件是否可用,适合连接数多的情况。

http://www.dtcms.com/a/583546.html

相关文章:

  • 【Three.js--manual script】4.光照
  • 小杰-大模型(one)——RAG与Agent设计——Langchain部署大模型。
  • UE5 C++ 进阶学习 小知识点 —— 01 - 本地化语言
  • 如何来构建一个成交型网站wordpress手机端和pc端兼容
  • 网站建设客户资料收集清单个人网站有哪些站
  • 搜狐快站怎么样wordpress 多说评论插件
  • 网站广告psdwordpress 产品多个分类
  • 浏览器收录网站惠州网站建设点
  • 重庆建设网站哪个好中国企业500强名单公布
  • 邹城建网站研究院网站建设方案
  • 岳阳网站开发商城广州工商学院门户网站
  • 淮北专业三合一网站开发苏州城乡建设网站查询
  • 深圳网站建设服务电话alexa全球网站排名
  • php做网站需要什么技术做网站开发哪里可以接单
  • .net 网站制作唐山炎黄宽带网站
  • 做运营必知网站温州网站开发技术
  • 电子商务知名网站wordpress电子邮件
  • 技术支持 金华网站建设seo关键词怎么选
  • 临沂企业网站建站模板图片发到哪些网站 seo
  • 12数据网站建设discuz主题模板
  • 招聘网站建设公司张掖市作风建设年活动网站
  • 网站建设大作业选题免费ppt模板可编辑
  • 国内网站建设建设峨边网站建设
  • 顺序表vector--------练习题7题解
  • 网站建设含义六盘水网络推广
  • 江北网站制作制作网页用什么语言
  • 校园视频网站建设房地产开发公司账务处理流程
  • 给网站做维护是什么工作关注公众号一单一结兼职app
  • 子午谷网站建设百度投诉中心24小时电话
  • 今日行情明日机会——20251107