[英]Non-blocking read on pipe
可以在管道上进行非阻塞 I/O 吗? fcntl 未能设置 O_NONBLOCK。 Linux 编程接口的第 918 页包含一个表“从管道或 FIFO (p) 读取 n 字节的语义”。 下表列出了管道和 FIFO 的行为,其中一列标题为启用了 O_NONBLOCK? 这意味着您可以在管道上设置 O_NONBLOCK 标志。 这个对吗? 以下代码未能设置标志,但 fcntl(2) 不报告错误。
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
int main()
{
int fds[2];
pid_t pid;
char wr_buf[100];
char rd_buf[100];
pipe(fds);
pid = fork();
if ( pid )
{
while (1 )
{
memcpy( wr_buf, "abcdefghi\0",10);
write( fds[1], wr_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], rd_buf, 10 );
printf("read: %d\n", r);
if ( r > 0 )
{
printf("Buffer: %s\n", rd_buf);
}
else
{
printf("Read nothing\n");
perror("Error was");
sleep(1);
}
}
}
}
pipe 和 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 status flags
:-)
来自man 3 fcntl
:
文件描述符标志以下命令操作与文件描述符关联的标志。 目前,只定义了一个这样的标志:FD_CLOEXEC,close-on-exec 标志。 如果 FD_CLOEXEC 位为 0,则文件描述符将在 execve(2) 中保持打开状态,否则将关闭。
文件状态标志每个打开的文件描述都有某些相关的状态标志,由 open(2) 初始化,并可能由 fcntl() 修改。 重复的文件描述符(使用 dup(2)、fcntl(F_DUPFD)、fork(2) 等)引用相同的打开文件描述,因此共享相同的文件状态标志。
F_SETFL (int) 将文件状态标志设置为 arg 指定的值。 arg 中的文件访问模式(O_RDONLY、O_WRONLY、O_RDWR)和文件创建标志(即 O_CREAT、O_EXCL、O_NOCTTY、O_TRUNC)被忽略。 在 Linux 上,此命令只能更改 O_APPEND、O_ASYNC、O_DIRECT、O_NOATIME 和O_NONBLOCK标志。 无法更改 O_DSYNC 和 O_SYNC 标志; 请参阅下面的错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.