Fre*_*ete 5 c c++ linux ipc named-pipes
我正在尝试在同一台机器上运行的两个不同程序(在我的情况下为CentOS7)之间实现IPC。为了只有一种松散耦合,我决定为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;
}
Run Code Online (Sandbox Code Playgroud)
读取管道:
#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;
}
Run Code Online (Sandbox Code Playgroud)
我觉得命名管道在我的测试程序中发现的行为非常不灵活。首先,如果未向fifo管道附加任何读取过程,则除写入该管道的最后一条消息以外的所有消息都将丢失(或者通常来说,将读取过程附加到该管道后,只能读取最后一条消息)。如果将多个消息写入管道,则读取之前的所有消息(例如,轮询的)将被解释为一条消息(我知道它们可以用\ 0分隔)。
命名管道的主要目标是a)系统日志和b)用户身份验证的种类。命名管道的异步非常适合我的需求。但是无论如何,我不确定命名管道是否是不同程序之间IPC的最佳解决方案。另外,我不确定上面描述的行为是否正常,或者我是否以错误的方式使用了命名管道。我也考虑过套接字,但是随后我将遇到巨大的阻塞问题。
谢谢你的帮助。
“首先,如果没有读取进程附加到 fifo 管道,则除了最后写入管道的消息之外的所有消息都会丢失”。
不,他们没有。使用cat而不是你的(写得很糟糕:D)阅读过程,你会得到所有的消息。
你是对的。管道是面向字节的,而不是面向消息的。如果您需要消息,还有其他 IPC(例如,SysV 消息队列)。
Beej 的《Unix IPC 指南》是对 Unix iPC 的出色介绍,如果您想要更高级的东西,那么Richard Stevens 的《Unix 环境中的高级编程》 非常好。
就用户身份验证而言,请查看 Unix 套接字。
看起来您正在尝试将管道用于其设计目的之外的用途。首先,必须为管道的另一侧“附加”读取过程。如果您尝试打开管道进行写入并且没有读取过程,open则会挂起等待它或返回 -1 并errno设置为ENXIO(当使用 O_NONBLOCK 标志时)。因此,命名管道是系统中的一种随机点,两个进程在此相遇以交换数据;)
其次 - 不要将写入管道视为发送消息。管道更像是“字节流”。您可以一次写入 10 个字节,读取器可以进行 5 次读取,每次读取 2 个字节,反之亦然:您可以写入 5 次 2 个字节,读取器可以一次读取它们。因此,如果您计划通过管道发送某种“消息”,您应该开发某种最小传输协议(例如使用“\0”字节作为分隔符,如上所述)。
因此,也许您应该查看 System V 消息队列(请参阅msgget、msgctl、msgrcv、msgsnd、 或 POSIX 消息队列(请mq_open参阅mq_unlink、mq_send、mq_receive等),它使您可以发送和接收“原子”消息。
| 归档时间: |
|
| 查看次数: |
8027 次 |
| 最近记录: |