簡體   English   中英

IPC:在兩個程序之間使用c ++中的命名管道

[英]IPC: Using of named pipes in c++ between two programs

我正在嘗試在同一台機器上運行的兩個不同程序之間實現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的最佳解決方案。 此外,我不確定上面描述的行為是否正常,或者我是否以錯誤的方式使用命名管道。 我也考慮過套接字,但后來我會遇到很大的阻塞問題。

謝謝你的幫助。

“首先,如果沒有讀取進程附加到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消息隊列(請參閱msggetmsgctlmsgrcvmsgsnd或POSIX消息隊列(請參閱mq_openmq_unlinkmq_sendmq_receive等),這樣您就可以發送和接收“原子”消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM