操作系统----阻塞读终端

来源:互联网 发布:网络推广计划方案 编辑:程序博客网 时间:2024/06/05 05:39
摘自《linux C语言编程一站式学习》
阻塞读终端
例子:
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
char buf[10];
int n;
n = read(STDIN_FILENO, buf, 10);
if (n < 0) {
perror("read STDIN_FILENO");
exit(1);
}
write(STDOUT_FILENO, buf, n);
return 0;
}
执行结果如下:
$ ./a.out
hello(回车)
hello
$ ./a.out
hello world(回车)
hello worl$ d
bash: d: command not found
分析:
第一次执行a.out的结果很正常,而第二次执行的过程有点特殊,现在分析一下:
1. Shell进程创建a.out进程, a.out进程开始执行,而Shell进程睡眠等待a.out进程退出。
2. a.out调用read时睡眠等待,直到终端设备输入了换行符才从read返回, read只读走10个字
符,剩下的字符仍然保存在内核的终端设备输入缓冲区中。
3. a.out进程打印并退出,这时Shell进程恢复运行, Shell继续从终端读取用户输入的命令,于
是读走了终端设备输入缓冲区中剩下的字符d和换行符,把它当成一条命令解释执行,结果发
现执行不了,没有d这个命令。
--------------------------------------------------分割线-------------------------------------------------------------
不阻塞读终端

如果在open一个设备时指定了O_NONBLOCK标志, read/write就不会阻塞。以read为例,如果设备暂
时没有数据可读就返回-1,同时置errno为EWOULDBLOCK(或者EAGAIN,这两个宏定义的值相同),
表示本来应该阻塞在这里( would block,虚拟语气),事实上并没有阻塞而是直接返回错误,调用
者应该试着再读一次( again)。这种行为方式称为轮询( Poll) ,调用者只是查询一下,而不是阻
塞在这里死等,这样可以同时监视多个设备:
while(1) {
非阻塞read(设备1);      //在linux系统中,设备1对应目录树下的一个设备文件,也就是文件 ,即read(文件名)
if(设备1有数据到达)
处理数据;
非阻塞read(设备2);      //在linux系统中,设备2对应目录树下的一个设备文件
if(设备2有数据到达)
处理数据;
...
}

如果read(设备1)是阻塞的,那么只要设备1没有数据到达就会一直阻塞在设备1的read调用上,即使
设备2有数据到达也不能处理,使用非阻塞I/O就可以避免设备2得不到及时处理。


原创粉丝点击