当前位置:嗨网首页>书籍在线阅读

02-阻塞与非阻塞IO

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

8.1 阻塞与非阻塞I/O

阻塞操作是指在执行设备操作时,若不能获得资源,则挂起进程直到满足可操作的条件后再进行操作。被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足。而非阻塞操作的进程在不能进行设备操作时,并不挂起,它或者放弃,或者不停地查询,直至可以进行操作为止。

驱动程序通常需要提供这样的能力:当应用程序进行read()、write()等系统调用时,若设备的资源不能获取,而用户又希望以阻塞的方式访问设备,驱动程序应在设备驱动的xxx_read()、xxx_write()等操作中将进程阻塞直到资源可以获取,此后,应用程序的read()、write()等调用才返回,整个过程仍然进行了正确的设备访问,用户并没有感知到;若用户以非阻塞的方式访问设备文件,则当设备资源不可获取时,设备驱动的xxx_read()、xxx_write()等操作应立即返回,read()、write()等系统调用也随即被返回。

阻塞从字面上听起来似乎意味着低效率,实则不然,如果设备驱动不阻塞,则用户想获取设备资源只能不停地查询,这反而会无谓地耗费CPU资源。而阻塞访问时,不能获取资源的进程将进入休眠,它将CPU资源“礼让”给其他进程。

因为阻塞的进程会进入休眠状态,因此,必须确保有一个地方能够唤醒休眠的进程,否则,进程就真的“寿终正寝”了。唤醒进程的地方最大可能发生在中断里面,因为硬件资源获得的同时往往伴随着一个中断。

代码清单8.1和8.2分别演示了以阻塞和非阻塞方式读取串口一个字符的代码。实际的串口编程中,若使用非阻塞模式,还可借助信号(sigaction)以异步方式访问串口以提高CPU利用率,而这里仅仅是为了说明阻塞与非阻塞的区别。

代码清单8.1 阻塞地读串口一个字符

char buf;

fd = open("/dev/ttyS1", O_RDWR);

...

res = read(fd,&buf,1); / 当串口上有输入时才返回 /

if(res==1)

printf("%c\n", buf);

代码清单8.2 非阻塞地读串口一个字符

char buf;

fd = open("/dev/ttyS1", O_RDWR| O_NONBLOCK);

...

while(read(fd,&buf,1)!=1)

continue; / 串口上无输入也返回,所以要循环尝试读取串口 /

printf("%c\n", buf);