本节讲解什么是非阻塞IO,如何将文件描述符修改为非阻塞式
3.6.1.1、阻塞与非阻塞
(1)阻塞是指函数调用会被阻塞。本质是当前进程调用了函数,进入内核里面去后,因为当前进程的执行条件不满足,内核无法里面完成操作,就挂起这个进程,去执行其他进程。默认使用阻塞IO
(2)非阻塞IO当条件不满足时直接停止当前操作,退出程序(?)。或者非阻塞IO条件不满足时会一直占用CPU资源
(3)结合程序状态转换图一起理解
3.6.1.2、为什么有阻塞式
(1)常见的阻塞:wait、pause、sleep等函数;read或write某些文件时
wait等待回收子进程:当子进程没死,父进程就不能回收子进程,内核就阻塞住父进程,知道子进程死去称为僵尸进程,这时内核就会发一个信号给父进程,父进程就会被唤醒,去回收子进程。
(2)阻塞式的好处
非常有利于OS的性能发挥。阻塞时不会占用CPU,CPU可以去执行其他。
3.6.1.3、非阻塞
(1)为什么要实现非阻塞
(2)如何实现非阻塞IO访问:O_NONBLOCK和fcntl
a -- 阻塞
阻塞操作是指在执行设备操作时,若不能获得资源,则挂起进程知道满足可操作的条件后再进行操作;被挂起的进程进入休眠状态(放弃CPU),被从调度器的运行队列移走,直到等待的条件被满足;
b -- 非阻塞
非阻塞的进程在不能进行设备操作时,并不挂起(继续占用CPU),它或者放弃,或者不停地查询,直到可以操作为止;
二者的区别可以看应用程序的调用是否立即返回!
驱动程序通常需要提供这样的能力:当应用程序进行 read()、write() 等系统调用时,若设备的资源不能获取,而用户又希望以阻塞的方式访问设备,驱动程序应在设备驱动的xxx_read()、xxx_write() 等操作中将进程阻塞直到资源可以获取,此后,应用程序的 read()、write() 才返回,整个过程仍然进行了正确的设备 访问,用户并没感知到;若用户以非阻塞的方式访问设备文件,则当设备资源不可获取时,设备驱动的 xxx_read()、xxx_write() 等操作立刻返回, read()、write() 等系统调用也随即被返回。
因为阻塞的进程会进入休眠状态,因此,必须确保有一个地方能够唤醒休眠的进程,否则,进程就真的挂了。唤醒进程的地方最大可能发生在中断里面,因为硬件资源获得的同时往往伴随着一个中断。
阻塞I/O通常由等待队列来实现,而非阻塞I/O由轮询来实现。