非阻塞I/O
阻塞I/O对应于低速的系统调用,可能会使进程永远阻塞。非阻塞I/O可以使我们发出open、read、write这样的I/O操作,并使这些操作不会永远阻塞。如果这种操作不能完成,则调用立即错误返回,其表示该操作如果继续执行将会阻塞。
对于一个给定的描述符,有两种为其指定非阻塞I/O的方法:
(1) 如果是调用open获得文件描述符,则可指定O_NONBLOCK标志。
(2) 对于一个已经打开的文件描述符,则可以调用fcntl,由该函数打开O_NONBLOCK文件状态标志。
如下是一个非阻塞I/O的实例,它从标准输入读500000个字节,并试图将它们写到标准输出上。该程序先将标准输出设置为非阻塞的,然后用for循环进行输出,每次write调用的结果都在标准错误上打印。
1 [root@benxintuzi IOpri]# cat nonblock.c 2 #include <unistd.h> 3 #include <errno.h> 4 #include <fcntl.h> 5 #include <stdio.h> 6 7 char buf[500000]; 8 9 void set_fl(int fd, int flags); 10 void clr_fl(int fd, int flags); 11 12 int main(void) 13 { 14 int ntowrite, nwrite; 15 char* ptr; 16 17 ntowrite = read(STDIN_FILENO, buf, sizeof(buf)); 18 fprintf(stderr, "read %d bytes\n", ntowrite); 19 20 set_fl(STDOUT_FILENO, O_NONBLOCK); /* set nonblocking */ 21 22 ptr = buf; 23 while (ntowrite > 0) 24 { 25 errno = 0; 26 nwrite = write(STDOUT_FILENO, ptr, ntowrite); 27 fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno); 28 29 if (nwrite > 0) 30 { 31 ptr += nwrite; 32 ntowrite -= nwrite; 33 } 34 } 35 36 clr_fl(STDOUT_FILENO, O_NONBLOCK); /* clear nonblocking */ 37 38 return 0; 39 } 40 41 void set_fl(int fd, int flags) /* flags are file status flags to turn on */ 42 { 43 int val; 44 45 if ((val = fcntl(fd, F_GETFL, 0)) < 0) 46 printf("fcntl F_GETFL error\n"); 47 48 val |= flags; /* turn on flags */ 49 50 if (fcntl(fd, F_SETFL, val) < 0) 51 printf("fcntl F_SETFL error\n"); 52 } 53 54 void clr_fl(int fd, int flags) /* flags are the file status flags to turn off */ 55 { 56 int val; 57 58 if ((val = fcntl(fd, F_GETFL, 0)) < 0) 59 printf("fcntl F_GETFL error\n"); 60 61 val &= ~flags; /* turn flags off */ 62 63 if (fcntl(fd, F_SETFL, val) < 0) 64 printf("fcntl F_SETFL error\n"); 65 } 66 67 [root@benxintuzi IOpri]# gcc nonblock.c -o nonblock 68 [root@benxintuzi IOpri]# ./nonblock < nonblock.c > temp.file 69 read 1246 bytes 70 nwrite = 1246, errno = 0 71 [root@benxintuzi IOpri]# ls -l temp.file 72 -rw-r--r--. 1 root root 1246 Sep 1 23:38 temp.file