簡體   English   中英

如何使用涉及多次讀寫的管道在子進程和父進程之間實現雙向通信

[英]How to implement two way communication between child and parent processes using pipes which involves multiple read and writes

我已經實現了一個涉及子進程和父進程之間的雙向通信的場景。 子進程使用 execvp 啟動另一個 c 程序(比如 XYZ)。 Parent 在 pipe1 的一端寫入數據,pipe1 的另一端被復制到 child 的標准輸入。 所以孩子讀取這些數據,執行一些操作並將數據寫回標准輸出。 此標准輸出被復制到 pipe2 的寫入端,現在父級從 pipe2 的讀取端讀取。 外部程序 XYZ 不可修改。 要遵循的順序是

1) parent 將數據寫入 pipe1 2) child 從 pipe1 的重復端 (stdin) 讀取數據 3) child 對數據進行一些修改並將數據寫回 stdout,stdout 被復制到 pipe2 的讀取端 4) parent 嘗試讀取數據從 pipe2 的讀取端開始。

上面的場景可以重復n次。

以上場景示例 1) 父級寫入 1 2) 子級讀取 1 並進行修改並將 1(修改后)寫入標准輸出 3) 現在父級讀取此數據並打印回 4) 打印后,父級將 2 寫入標准輸入 5 ) 繼續如上.....

我面臨的問題是父級無法從 pipe2 的讀取端讀取數據。 它實際上是閑逛。

Imp 注意:我沒有關閉 pipe1 的寫句柄,因為我需要重新寫入數據。 如果我關閉手柄,我無法重新打開它,因為它不受管道支持。

代碼如下圖

void Child_write  (pid_t Handle);
void Parent_write (pid_t Handle, char c);
void Child_read  (pid_t Handle);
void Parent_read (pid_t Handle);

void main()
{

  pid_t Pid;
  int   writepipe[2],readpipe [2];  

  pipe(readpipe);               /* Create two file descriptors  */
  pipe(writepipe);              /* Create two file descriptors  */

  Pid = fork();

  if (Pid == 0)         
  {
     close(writepipe[1]);               /* closing writepipe's write end */
     dup2(writepipe[0],0); close(writepipe[0]);     /* duplicating writepipe's read    end to stdin*/
     close(readpipe[0]);                /* closing readpipe's read end*/
     dup2(readpipe[1],1);  close(readpipe[1]);      /* duplicating readpipe's write end to stdout*/    
     Child_read(writepipe[0]);              /* reading data from write pipe read end and then duplicating*/

  }
  else                  
  {
     close(writepipe[0]);               /* closing writepipe's read end */
     Parent_write(writepipe[1],'1');            /* pupming data to the writepipe */
     close(readpipe[1]);                /* closing the readpipes write end */
     Parent_read(readpipe[0]);              /* reading the data which is pumped into readpipe */
     //Parent_write(writepipe[1],'2');          /* pupming data to the writepipe */
     //Parent_read(readpipe[0]);

     //Parent_write(writepipe[1],'3');
     //Parent_read(readpipe[0]);
     puts("***** End of parent process*****");
  }
}

void Child_read(pid_t handle)
{
   static char* command = "./stdoutput";
   execvp(command, NULL);
}

void Parent_write(pid_t handle, char c)
{
   char Buff[] = {'\n','\n'};
   Buff[0] = c;
   int n_written= write(handle, Buff, strlen(Buff)+1);

   printf("write function has written %d no of bytes and the data written is %s",n_written,Buff);

   //close(handle);
}

void Parent_read(pid_t handle)
{
    printf("PARENT PROCESS: In Parent_read function\n");
    int i=0;
    int bytes_read = 0;
    char buffer[1024]= {'\0'};
    while (read(handle, buffer, sizeof(buffer)) > 0)
    {
        printf("PARENT PROCESS:: In while loop\n");
        printf("The character/string read from readend of readpipe (stdout) is %s",buffer);
    }
    close(handle);
}

外部程序如下圖

void printing()
{
  int c;
  do
    {
        c = getchar();
        printf("%c",c);
    } while ((c != EOF) && (c != '\n'));
}

void main()
{
  printing();
  printing();
}

請幫我 !!!!!!!!!

在針對給定 FILE * 的第一次 I/O 調用(使用文件 stream 函數)時,庫決定 stream 應該是行緩沖、塊緩沖還是非緩沖。 在您的情況下,當 stdoutput 啟動時,它的 stdoutput 不是終端,因此 stream 進入塊緩沖模式,而您的 printf 在緩沖區中結束。

將您的主要 function 更改為:

void main()
{
  setvbuf(stdout, NULL, _IONBF, 0);
  printing();
  printing();
}

您的 printf 調用將產生寫入。

您還應該查看setvbuf手冊頁,並學習使用 strace:

strace -ff -o test.log ./myprog

將產生兩個日志文件(一個給父級,一個給子級),讓您看到每個程序進行了哪些系統調用。

確實,正如 Jerry Coffin 評論的那樣,您應該使用popen (某些系統也有用於雙向管道的p2open ,一個輸入,另一個輸出)。

如果你真的堅持自己做,你應該強烈考慮使用像poll這樣的多路復用系統調用(或者可能是更老的select )。 然后您將能夠測試可以讀取或寫入哪個文件描述符,並采取相應的行動。

暫無
暫無

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

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