系统调用分为两类:低速系统调用和其它系统调用。
而低速系统调用可能使进程永远阻塞。
低速系统调用包括:
1:在读某些类型的文件(管道,终端设备及网络设备)时,如果数据并不存在则可能会使调用者永远阻塞。
2:如果数据不能立即被上述同样类型的文件接受(由于在管道中无空间、网络流控制等),则写操作也会使调用者阻塞。
3:在某种条件发生之前,打开某种类型的文件会被阻塞(例如打开一个终端设备可能需等到与之链接的调制解调器应答;又例如在没有其它进程已用读模式打开该FIFO时若以只写方式打开FIFO,也要等待。
4:对已经加上强制性记录锁的文件进行读、写。
5:某些ioctl操作
6:某些进程间通信函数(看了进程间通信后尝试列举出是哪些进程间通信)
非阻塞I/O含义:非阻塞I/O使我们调用open,read,write这样的I/O操作,并使这些操作永远不会阻塞。如果这种操作不能完成,则立即出错返回,表示该操作继续执行将阻塞。
指定文件描述符非阻塞的方法:
如果调用open函数获取描述符,可指定O_NONBLOCK标志
对于已打开的一个描述符,可调用fcntl函数,由该函数打开O_NONBLOCK文件状态标志(最好先获取文件状态标志,再在原来的基础上和O_NONBLOCK做或运算)
-
#include
-
#include
-
#include<errno.h>
-
#include<fcntl.h>
-
-
char buf[500000];
-
int main(void)
-
{
-
int ntowrite,nwrite;
-
char*ptr;
-
ntowrite=read(STDIN_FILENO,buf,sizeof(buf));
-
fprintf(stderr,"read %d bytes\n",ntowrite);
-
-
struct stat ino_buf;
-
int fl=-1;
-
if((fl=fcntl(STDOUT_FILENO,F_GETFL))==-1){
-
puts("get stdout stat failed");
-
return errno;
-
}
-
if(fcntl(STDOUT_FILENO,F_SETFL,fl|O_NONBLOCK)==-1){
-
puts("set file stat failed");
-
return errno;
-
}
-
ptr=buf;
-
while(ntowrite>0){
-
errno=0;
-
nwrite=write(STDOUT_FILENO,ptr,ntowrite);
-
fprintf(stderr,"nwrite=%d,errno=%d\n",nwrite,errno);
-
-
if(nwrite>0){
-
ptr+=nwrite;
-
ntowrite-=nwrite;
-
}
-
}
-
if(fcntl(STDOUT_FILENO,F_SETFL,fl|~O_NONBLOCK)==-1){
-
puts("recover file stat failed");
-
return 1;
-
}
-
exit(0);
-
}
我先用dd命令复制一个702559字节的文件,然后将它作为程序的标准输入,并把程序的标准输出重定向到文件,结果显示一次性write成功。第二次标准输入不变,标准输出重定向到终端,标准错误输出重定向到stderr.out文件,然后我们查看标准错误输出文件,问了节省空间,我只截取了一部分,可以看到并不是每次都调用成功的,与文章最上面低速系统调用第二项吻合,当调用可能阻塞时会立即出错返回。
阅读(563) | 评论(0) | 转发(0) |