我正在尝试在同一台计算机上的两个不同程序之间实现IPC(在我的情况下,是CentOS7)。为了实现松散的耦合,我决定使用一个命名管道进行IPC。因此,我正在使用以下示例并遇到了不同的问题。
创建并写入管道:
创建并写入管道:
#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;
}
读取管道:
#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;
}
我觉得命名管道在行为上相当不灵活,通过我的测试程序我已经找出了其中的问题。首先,如果没有任何读进程附加到FIFO管道,那么除了最后一个写入管道的消息外,所有消息都会丢失(或者一般来说,只有在读进程附加到管道后才能读取最后一个消息)。如果您将多个消息写入管道,则在读取(例如轮询)之间的所有消息都将被解释为单个消息(我知道它们可以通过 \0 分割)。
命名管道的主要目标是a)系统日志和b)某种形式的用户身份验证。命名管道的异步特性非常适合我的需求。但无论如何,我不确定命名管道是否是不同程序之间进行IPC的最佳解决方案。此外,我也不确定上述描述的行为是正常的,还是我使用命名管道的方式有误。我也考虑过套接字,但这样会遇到巨大的阻塞问题。
感谢您的帮助。