gpt4 book ai didi

c - 使用 select 以非阻塞模式打开 fifo

转载 作者:IT王子 更新时间:2023-10-29 00:41:53 27 4
gpt4 key购买 nike

我有两个进程 A 和 B。通信流始终是 A -> B,但我需要使用命名管道来完成,因为我必须在 B 进程内的选择调用中使用管道文件描述符,并且当任何一个或两个进程退出时,写入管道的数据必须保留。

管道在两端以非阻塞模式打开。在进程A中:

int push_fifo_fd = open(FIFO_NAME, O_WRONLY | O_NONBLOCK | O_CREAT, 0644);

进程B中:

int fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK | O_CREAT, 0644);

Q1。进程 B 使用 curl 多接口(interface),所以我获取 curl 多句柄的 fd_sets,并将“fd”描述符添加到读取的 fd_set,然后调用 select,以获取可用于读写的文件描述符。在每次调用select时,结果read fd_set中都包含“fd”,但是read返回0,即使write端打开了。这导致进程 B 使用 100% 的处理器时间。我提到我不知道打开管道末端的顺序。 B的相关代码:

while (1)
{
fd_set read_fds, write_fds, err_fds;

FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&err_fds);

FD_SET(fifo_fd, &read_fds);
// some code
ccode = curl_multi_fdset(curlm, &read_fds, &write_fds, &err_fds, &max_fd);
max_fd = MAX(max_fd, fifo_fd);

rc = select(max_fd + 1, &read_fds, &write_fds, &err_fds, &timeout);
switch (rc)
{
case -1:
WARN("select");
continue;

case 0:
default:
{
if (FD_ISSET(fifo_fd, &read_fds))
{
// read from the fifo_fd
}

/* Now look at the handles that need attention */
int old_running_handles = running_handles;

ccode = curl_multi_perform(curlm, &running_handles);
if (ccode != CURLM_OK && ccode != CURLM_CALL_MULTI_PERFORM)
{
WARN("curl_multi_perform error: %s", curl_multi_strerror(ccode));
continue;
}

if (running_handles != old_running_handles)
{
CURLMsg *curl_msg;
int left_msgs = 0;
while ((curl_msg = curl_multi_info_read(curlm, &left_msgs)) != NULL)
{
// treat each easy handle
}
}
}
break;
}
}

Q2。在“man 7 fifo”中说“一个进程可以在非阻塞模式下打开一个 FIFO。在这种情况下,即使没有人在写端打开,只读打开也会成功,只写打开将失败使用 ENXIO(没有这样的设备或地址),除非另一端已经打开。”但是进程A总是可以以非阻塞模式成功打开管道的写端,即使读端没有打开。这是为什么?我测试的平台是Ubuntu server 12.04.3,kernel 3.8.0-29。

最佳答案

select()poll() 期望 Q1。查看linked question .一个优雅的解决方案是在同一个 fifo 上打开另一个 fd 并关闭原始文件。

我相信某些版本的内核也预计会出现 Q2。 man 7 fifo有一个关于它的段落:

   Under Linux, opening a FIFO for read and write will succeed both in 
blocking and nonblocking mode. POSIX leaves this behavior undefined.
This can be used to open a FIFO for writing while there are no
readers available.

该段似乎声称您可以随时成功打开 fifo 的写入端,正如原作者在 Q2 中观察到的那样。

虽然它似乎与前一段相矛盾,因为原始问题也引用自 man 7 fifo基本上说打开应该失败而不是成功的页面:

   A process can open a FIFO in nonblocking mode.  In this case, opening
for read-only succeeds even if no one has opened on the write side
yet and opening for write-only fails with ENXIO (no such device or
address) unless the other end has already been opened.

我看到在 4.9.37 内核上,当读端未打开时,以非阻塞模式打开写端将失败。我猜它一定是从 3.8 版更改为 4.9 版。

关于c - 使用 select 以非阻塞模式打开 fifo,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19592039/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com