gpt4 book ai didi

c - 如何在 Linux 中读取和写入 fifo(命名管道)?

转载 作者:太空宇宙 更新时间:2023-11-04 07:59:56 24 4
gpt4 key购买 nike

我正在尝试打开一个 fifo(命名管道)文件,然后写入它。我似乎无法让服务器看到“客户端”向其写入的内容。

注意:为了简单起见,我使用了诸如“客户端-服务器”之类的术语。我意识到他们实际上只是同行,任何一方都可以关闭管道。

pipetest_server.c

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

int keep_going = 1;

static void signal_handler(int signum)
{
keep_going = 0;
}

int main()
{
int fd;
char *myfifo = "/tmp/mypipe";
char *line;
ssize_t amount_read;
ssize_t len;
FILE *f;

signal(SIGINT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);

// make pipe
mkfifo(myfifo, 0666);

// open it
fd = open(myfifo, O_RDWR);

// make non-blocking
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);

// make a file descriptor for pipe
f = fdopen(fd, "rw");

while(keep_going)
{
amount_read = getline(&line, &len, f);
if (amount_read > 0)
printf(line);
}

printf("quitting...\n");

close(fd);

unlink(myfifo);

return 0;
}

然后:

$ gcc pipetest_server.c
$ ./a.out

在另一个终端:

$ ls -la /tmp/mypipe
prw-rw-r--. 1 myuser myuser 0 Nov 20 12:58 /tmp/mypipe

好的——此时,那里有一根管道。现在解决问题

1) 用回显写入管道。什么都没发生

$ echo Hi >> /tmp/mypipe
<nothing comes out of the server>

2) Cat'ing the pipe,显示数据

$ cat /tmp/mypipe
Hi
<blinking cursor>

发生了什么....

服务器永远不会获取数据,但管道中有数据。

3) 当我关闭服务器时,管道消失了

<ctrl-C>
^Cquitting...

这告诉我服务器确实创建了管道并控制了它。

4) 我真的很想创建另一个程序来写入管道

最终,我想要另一个程序写入这个管道,这两个程序将通过它进行通信。

注意:还有其他关于此的 SO 文章,但没有一篇恰到好处。

更新——工作代码

这是最后的解决方案,以防万一。

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

static volatile sig_atomic_t keep_going = 1;

static void signal_handler(int signum)
{
keep_going = 0;
}

int main()
{
int fd;
char *myfifo = "/tmp/mypipe";
char *line;
ssize_t amount_read;
ssize_t len;
FILE *f;

signal(SIGINT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);

// make pipe
mkfifo(myfifo, 0666);

// open it
fd = open(myfifo, O_RDWR);

// make non-blocking
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);

// make a file descriptor for pipe
f = fdopen(fd, "rw");

while(keep_going)
{
amount_read = getline(&line, &len, f);
if (amount_read > 0)
printf(line);
if (amount_read == -1)
{
clearerr(f);
}
}

printf("quitting...\n");

close(fd);

unlink(myfifo);

return 0;
}

最佳答案

问题是您已将文件描述符设置为非阻塞,然后使用 fdopen 在其上打开了一个 FILE *。 Stdio FILE 流不理解非阻塞 I/O,因此在您的第一个 getline 调用中,读取将失败(使用 EWOULDBLOCK 或 EGAIN)并且 FILE 将进入错误状态,并且 getline 将返回 - 1.一旦 FILE 处于错误状态,每次调用都会立即返回 -1,而不会真正尝试再次读取。

如果要真正使用非阻塞模式,需要在getline返回-1后调用clearerr(f)。您还应该检查 errno,以确保错误是 EWOULDBLOCK 或 EAGAIN——如果存在真正的错误,那将是其他错误。

关于c - 如何在 Linux 中读取和写入 fifo(命名管道)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47399352/

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