我正在尝试打开一个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写入管道。没有任何事情发生
$ echo Hi >> /tmp/mypipe
<nothing comes out of the server>
2)捕捉管道,显示数据
$ 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;
}
答案 0 :(得分:2)
问题是您已将文件描述符设置为非阻塞,然后使用fdopen在其上打开FILE *
。 Stdio FILE流不理解非阻塞I / O,因此在第一次getline
调用时,读取将失败(使用EWOULDBLOCK或EGAIN)并且FILE将进入错误状态,并且getline将返回-1。一旦FILE处于错误状态,每次调用都会立即返回-1而不会再次尝试再次读取。
如果您想实际使用非阻塞模式,则需要在getline返回-1后调用clearerr(f)
。您还应该检查错误,以确保错误是EWOULDBLOCK或EAGAIN - 如果出现真正的错误,它将是其他错误。