簡體   English   中英

Unix:如果進程終止,管道(半雙工)會發生什么

[英]Unix : What happens to a pipe(half-duplex) if the process dies

我試圖證明我的疑問之一,即兩個不相關的進程可以共享半雙工管道的fd並進行通信。

我為此創建了兩個程序。 但是后來我又有了另一個問題,如果進程死了,那該怎么辦?因為當我打印出消息時,我的讀者收到了一些垃圾消息。

作家

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int fd[2];
    char str[] = "hello\n";
    if(pipe(fd) < 0)
        perror("Pipe creation failed\n");

    //Since i am a writer, i should close the reading end as a best practice
    close(fd[0]);

    /*
    The processes need not to be related processes, in order to use the half duplex pipes. fd is just a number/identifier
    which can be shared across different processes 
    */
    printf("Hey there !!! use this file descriptor for reading : %d\n", fd[0]);

    //writing message   
    write(fd[1],str,strlen(str)+1);
    return 0;
}

讀者

#include <stdio.h>
#include <unistd.h>

int main()
{
    int fd,bytesRead;
    char buffer[1024];

    printf("please enter the fd :");
    scanf("%d",&fd);

    bytesRead = read(fd,buffer,1024);

    printf("Bytes Read : %d\nMessage : %s\n", bytesRead, buffer);
    return 0;
}

你做不到

文件描述符表是每個進程的; 每個進程都有其自己的單獨的打開文件描述符集(請注意,每個文件的打開文件描述符與每個系統范圍的打開文件描述之間的區別,在open(2)了討論)。 如果要在進程間共享一個文件描述符,你需要或者繼承它在fork(2)或通過把它傳遞unix(7)域套接字經由sendmesg(2)SCM_RIGHTScmesg(3)報頭。

(在Linux上,您還可以傳遞/proc/[PID]/fd/...路徑,其他系統可能有其自己的不可移植等效項)。

在您的情況下發生的事情是讀取失敗(您為它提供了一個未打開的文件描述符),從而使緩沖區中留有未初始化的垃圾。 由於您不檢查返回值,因此您永遠不會知道它失敗了。

在管道手冊頁中,

pipe()創建一個管道,一個可用於進程間通信的單向數據通道。 數組pipefd用於返回兩個引用管道末端的文件描述符。 pipefd [0]指向管道的讀取端。 pipefd [1]指向管道的寫端。 寫入管道的寫入端的數據由內核緩沖,直到從管道的讀取端讀取數據為止。

該管道主要用於相關過程(父子進程)。 您無法將管道用於無關的過程。

在相關過程中,一端是封閉的。 在另一端過程中得到SIGPIPE信號。

使用管道的示例程序:-

   #include <sys/wait.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <unistd.h>
   #include <string.h>

   int
   main(int argc, char *argv[])
   {
       int pipefd[2];
       pid_t cpid;
       char buf;

       if (argc != 2) {
        fprintf(stderr, "Usage: %s <string>\n", argv[0]);
        exit(EXIT_FAILURE);
       }

       if (pipe(pipefd) == -1) {
           perror("pipe");
           exit(EXIT_FAILURE);
       }

       cpid = fork();
       if (cpid == -1) {
           perror("fork");
           exit(EXIT_FAILURE);
       }

       if (cpid == 0) {    /* Child reads from pipe */
           close(pipefd[1]);          /* Close unused write end */

           while (read(pipefd[0], &buf, 1) > 0)
               write(STDOUT_FILENO, &buf, 1);

           write(STDOUT_FILENO, "\n", 1);
           close(pipefd[0]);
           _exit(EXIT_SUCCESS);

       } else {            /* Parent writes argv[1] to pipe */
           close(pipefd[0]);          /* Close unused read end */
           write(pipefd[1], argv[1], strlen(argv[1]));
           close(pipefd[1]);          /* Reader will see EOF */
           wait(NULL);                /* Wait for child */
           exit(EXIT_SUCCESS);
       }
   }

上面的程序創建一個管道,然后fork(2)創建一個子進程。 子級繼承了引用同一管道的重復的文件描述符集。 在fork(2)之后,每個進程都關閉不需要管道的描述符(請參閱pipe(7))。 然后,父級將程序的命令行參數中包含的字符串寫入管道,而子級一次從管道讀取該字符串一個字節,並在標准輸出中回顯該字符串。

暫無
暫無

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

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