可以在管道上进行非阻塞I / O吗? fcntl无法设置O_NONBLOCK。 Linux编程接口的页面918包括一个从管道或FIFO(p)读取n个字节的表格#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_NONBLOCK\n");
exit(EXIT_FAILURE);
}
wait(NULL);
exit(EXIT_SUCCESS);
}
答案 0 :(得分:7)
管道和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\0",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: %d\n", retval);
while (1)
{
ssize_t r=read( fds[0], buf, 10 );
printf("read: %d\n", r);
if ( r > 0 )
{
printf("Buffer: %s\n", buf);
}
else
{
printf("Read nothing\n");
perror("Error was");
sleep(1);
}
}
}
}
写完我的例子后,我检查你的代码,发现:
flags = fcntl(pfd[0], F_GETFD);
flags |= O_NONBLOCK;
if (fcntl(pfd[0], F_SETFD, flags))
请将F_SETFD
更改为F_SETFL
以及获取操作。您不会更改file descriptor flags
,而是更改file descriptor status flags
: - )
来自man 3 fcntl
:
文件描述符标记 以下命令处理与文件关联的标志 描述。目前,只定义了一个这样的标志:FD_CLOEXEC ,. 近距离执行标志。如果FD_CLOEXEC位为0,则为文件描述符 将在执行人员(2)之间保持开放,否则将被关闭。
文件状态标记 每个打开的文件描述都有一些相关的状态标志,ini 由open(2)tialized并可能由fcntl()修改。重复的文件 描述符(用dup(2),fcntl(F_DUPFD),fork(2)等制作)是指 相同的打开文件描述,从而共享相同的文件状态 标志。
F_SETFL(int) 将文件状态标志设置为arg指定的值。文件 访问模式(O_RDONLY,O_WRONLY,O_RDWR)和文件创建标志 arg中的(即O_CREAT,O_EXCL,O_NOCTTY,O_TRUNC)将被忽略。 在Linux上,此命令只能更改O_APPEND,O_ASYNC, O_DIRECT,O_NOATIME和 O_NONBLOCK 标志。这不可能 更改O_DSYNC和O_SYNC标志;见下面的BUGS。