linux – 管道上的非阻塞读取
可以在管道上进行非阻塞I / O吗? fcntl无法设置O_NONBLOCK.
Linux编程接口的页面918包括一个表’从管道读取n个字节或FIFO(p)’的语义.此表列出了管道和FIFO的行为,其中一列标题为O_NONBLOCK已启用?这意味着您可以在管道上设置O_NONBLOCK标志.它是否正确?以下代码无法设置标志,但fcntl(2)不报告错误.
#include <fcntl.h> #include <sys/wait.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #define SLEEP 1 int main(int argc,char *argv[]) { pid_t childPid; int pfd[2]; int nread,flags; int c = 'a'; setbuf(stdout,NULL); if (pipe(pfd) == -1) { printf("error: pipe"); exit(EXIT_FAILURE); } switch (childPid = fork()) { case -1: printf("error: fork"); exit(EXIT_FAILURE); case 0: /* child */ if (close(pfd[0]) == -1) { printf("child: close pfd read"); exit(EXIT_FAILURE); } sleep(SLEEP); _exit(EXIT_SUCCESS); default: break; /* parent falls through */ } if (close(pfd[1]) == -1) { printf("parent: close pipe write"); exit(EXIT_FAILURE); } flags = fcntl(pfd[0],F_GETFD); flags |= O_NONBLOCK; if (fcntl(pfd[0],F_SETFD,flags)) perror("fcntl"); /* verify flags set correctly */ flags = fcntl(pfd[0],F_GETFD); if (!(flags & O_NONBLOCK)) { printf("failed to set O_NONBLOCKn"); exit(EXIT_FAILURE); } wait(NULL); exit(EXIT_SUCCESS); } 解决方法
管道和O_NONBLOCK没有什么特别之处.以下示例按预期工作.我没有检查每次调用的每个retval,以使示例更具可读性.真实世界的应用程序必须进行检查.
#include <unistd.h> #include <stdio.h> #include <string.h> #include <fcntl.h> int main() { int fds[2]; pid_t pid; char buf[100]; pipe(fds); pid = fork(); if ( pid ) { while (1 ) { memcpy( buf,"abcdefghi ",10); write( fds[1],buf,10); sleep(2); } } else { int retval = fcntl( fds[0],F_SETFL,fcntl(fds[0],F_GETFL) | O_NONBLOCK); printf("Ret from fcntl: %dn",retval); while (1) { ssize_t r=read( fds[0],10 ); printf("read: %dn",r); if ( r > 0 ) { printf("Buffer: %sn",buf); } else { printf("Read nothingn"); perror("Error was"); sleep(1); } } } } 写完我的例子后,我检查你的代码,发现: flags = fcntl(pfd[0],F_GETFD); flags |= O_NONBLOCK; if (fcntl(pfd[0],flags)) 请将F_SETFD更改为F_SETFL以及get操作.您不会更改文件描述符标志,但文件描述符状态标志:-) 来自man 3 fcntl:
|