阻塞和非阻塞I/O

下面就简单的介绍下阻塞和非阻塞I/O的区别

当应用程序发出一个阻塞系统调用的时候,应用程序的执行就会被挂起,应用程序是会从操作系统的运行队列移到等待队列上,当系统调用完成之后,应用程序就会移回到运行队列,可以继续执行并能收到系统调用返回的值

对于非阻塞的I/O,其实一个例子就是一个视频应用程序,它用来从磁盘文件上读取帧,同时解压缩并在显示器上进行输出

我们的进程当中有可能含有多个线程,那么就可以让有的线程执行阻塞系统调用,而其他线程继续执行,进程可以很好的工作

有的操作系统会提供非阻塞系统调用,一个非阻塞调用其实也并非是完全非阻塞的,通常都是通过设置超时来读取数据的。未超时之前,程序阻塞在读写函数上;超时后,结束本次读取,将已读到的数据返回。通过不断循环读取,就能够读到完整数据了。如果多次连续超时读到空数据的话,则可以断开当然这仅仅是一个思路

有一个非阻塞IO的例子就是用于网络Socket的select()系统调用

函数原型

int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);

  • 如果将NULL以形参传入,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止

  • 若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值

  • timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,若超出timeout的时间,select返回0,若发生错误返回负值

select函数只是检查是否可以进行I/O处理,对于数据的传输,还是需要在select()函数之后可以去需要使用read()或者是write()命令

其实除了非阻塞系统调用之外,还有异步系统调用。异步系统调用不必等待I/O完成就可以立即返回,这样应用程序就可以继续执行其的代码,在将来I/O完成的时候就可以去通知应用程序,通知方式可以是去设置应用程序地址空间内的某个变量,或者是通过触发信号或者是软件中断的形式还可以是应用程序执行流程之外的某个回调函数

非阻塞与异步系统调用的差别就是非阻塞read()调用会马上返回任何可用的数据,这个读取的数据可以等于或者少于所要求的,异步通信机制的话,可以理解为书店老板直接告诉你,他要查一下啊,查好了再打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调,异步read()调用所要求的传输应该是完整的执行的

同步和异步关注的是消息通信机制,阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

这里写图片描述

猜你喜欢

转载自blog.csdn.net/zcmuczx/article/details/80721504