IPC:在两个程序之间在c ++中使用命名pipe道

我试图实现在同一台机器上运行的两个不同程序(在我的情况下,它是一个CentOS7)之间的IPC。 为了只是一种松散的耦合,我决定使用IPC的命名pipe道。 因此,我正在玩下面的例子,遇到了不同的问题。

创build并写入pipe道:

#include <sys/types.h> #include <sys/select.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <string.h> using namespace std; main() { int fd; char * myfifo = new char [12]; strcpy(myfifo, "./tmp/myfifo1"); /* create the FIFO (named pipe) */ mkfifo(myfifo, 0666); /* write "Hi" to the FIFO */ fd = open("./tmp/myfifo1", O_WRONLY ); //open(myfifo, O_WRONLY | O_NONBLOCK); if (fd == -1) { perror("open"); return EXIT_FAILURE; } printf("File open\n"); write(fd, "entry [1]", sizeof("entry [1]")); sleep(1); write(fd, "entry [2]", sizeof("entry [2]")); sleep(2); write(fd, "entry [3]", sizeof("entry [3]")); printf("Content written\n"); close(fd); printf("Connection closed\n"); /* remove the FIFO */ unlink(myfifo); return 0; } 

读取pipe道:

 #include <sys/types.h> #include <sys/select.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <string> #include <iostream> using namespace std; main() { int fd; fd_set set_a; char * myfifo = new char [12]; strcpy(myfifo, "./tmp/myfifo1"); char buffer[1024]; fd = open("./tmp/myfifo1", O_RDONLY | O_NONBLOCK); if (fd == -1) { perror("open"); return EXIT_FAILURE; } ssize_t bytes; size_t total_bytes = 0; printf("\nDropped into read pipe\n"); while(1){ if((bytes = read(fd, buffer, sizeof(buffer))) > 0){ std::string message(&buffer[22]); total_bytes += (size_t)bytes; printf("%i", bytes); printf("Message: %s\n", message.c_str()); memset(&buffer[0], 0, sizeof(buffer)); }else{ if (errno == EWOULDBLOCK) { printf("\ndone reading (%d bytes)\n", (int)total_bytes); //break; } printf("No message\n"); sleep(2); } } return EXIT_SUCCESS; } 

我觉得像命名pipe道的行为是非常不灵活的,我想出了我的testing程序。 首先,如果没有读取过程被附加到fifopipe道上,除了写入pipe道的最后一个消息之外的所有消息都会丢失(或者一般而言,读取过程被附加到pipe道后,只能读取最后一个消息)。 如果在pipe道中写入多条消息,读取之间的所有消息(例如轮询)将被解释为单个消息(我知道它们可以被\ 0分割)。

命名pipe道的主要目标是a)系统日志和b)用户authentication的types。 命名pipe道的asynchronous完全符合我的需要。 但无论如何,我不确定命名pipe道是不同程序间IPC的最佳解决scheme。 此外,我不知道上面描述的行为是正常的,或者如果我用错误的方式使用命名pipe道。 我也想过套接字,但是接下来我会遇到巨大的阻塞问题。

谢谢你的帮助。

“首先,如果没有读取过程被附加到FIFO管道,除了写入管道的最后一个消息之外的所有消息都将丢失”。

不,他们不。 使用cat而不是你的(糟糕的书面:D)阅读过程,你会得到所有的消息。

你是对的。 管道是面向字节的,而不是面向消息的。 如果你想要消息,还有其他的IPC(例如,SysV消息队列)。

http://beej.us/guide/bgipc/output/html/singlepage/bgipc.html是Unix ipc的一个很好的介绍,如果你想要更高级的东西,那么Richard Stevens 在Unix环境下的高级编程是非常好的。

就用户身份验证而言,请查看Unix套接字。

看起来你正在试图用管道来设计他们没有设计的东西。 首先,管道的另一端必须有 “附加”的阅读过程。 如果您尝试打开管道进行写入,并且没有读取过程,则open将挂起等待,或者返回-1,并将errno设置为ENXIO (使用O_NONBLOCK标志时)。 如此命名的管道是系统中的一种规划点,其中两个进程相遇以交换数据;)

其次 – 不要把文字写入管道来发送信息。 Pipe是一个“字节流”。 您可以一次写入10个字节,读取器每次可以读取2个字节,反之亦然:您可以写入5个2字节,读者可以一次读取它们。 因此,如果您打算在管道上发送某种“消息”,则应该开发某种最小传输协议(例如,使用'\ 0'字节作为分隔符,如上所述)。

所以,也许你应该看看System V消息队列(参见msggetmsgctlmsgrcvmsgsnd或者POSIX消息队列(参见mq_openmq_unlinkmq_sendmq_receive等),这样就可以发送和接收'atomic'消息。