進程間通信(上)

管道

管道分為兩種類型:全雙工管道與半雙工管道。半雙工管道即意味著數據只能在一個方向上流動。全雙工管道上的數據可以兩個方向流動。老舊系統上大多不提供全雙工管道,所以為了移植性考慮,應主要使用半雙工管道。通常管道只能在具有公共祖先的兩個進程間使用。

盡管有局限性,但是半雙工管道仍舊是最常用的進程間通信方式。管道通過pipe()函數創建。

      int pipe(int fd[2]);

fd返回兩個文件描述符,fd[0]為讀而打開,fd[1]為寫而打開。我們通過一個例子來說明。

      int fd[2];
      char line[length];
      pipe(fd);
      if(pid = fork()>0) {
          close(fd[0]);
          write(fd[1], "hello world!\n", 12);
      }//parent
      else {
          close(fd[1]);
          n = read(fd[0], line, length);
          printf("%s", line);
      }//child

首先我們創建一個半雙工管道,然后通過fork()函數生成子進程。子進程會繼承父進程的所有文件描述符,顯然fd[0]、fd[1]都繼續保存著。然后父進程關閉讀通道,子進程關閉寫通道,父進程向半雙工管道寫入一串字符串,然后子進程讀入后寫入標準輸出。

其實實現全雙工管道也不是一件復雜的事。我們只需要建立兩個半雙工管道即可。

      int fd1[2],fd2[2];
      char line1[length],line2[length];
      pipe(fd1);
      pipe(fd2);
      if(pid = fork()>0) {
          close(fd1[0]);
          close(fd2[1]);
          write(fd1[1], "hello world!\n", 12);
          read(fd2[0],line1,length);
          printf("%s", line1);
      }//parent
      else {
          close(fd1[1]);
          close(fd2[0]);
          n = read(fd1[0], line, length);
          write(fd2[1], "hello world!\n", 12);
          printf("%s", line2);
      }//child

FIFO

FIFO有時被稱為命名管道。未命名的管道只能在兩個有共同祖先的進程之間使用。FIFO是一個半雙工管道。

FIFO由mkfifo()函數創建。

      int mkfifo(const char *pathname, mode_t mode);

mode參數指定文件權限位,類似于open函數的第二個參數。而pathname是一個普通的Unix路徑名,代表FIFO的位置。

需要注意的是mkfifo()函數只能創建一個新的管道,而打開一個新的管道只能用open()函數。

      #define FIFO1 "tmp/fifo.1"
      #define FIFO2 "tmp/fifo.2"
      char line1[length],line2[length];
      mkfifo(FIFO1, FILE_MODE);
      mkfifo(FIFO2, FILE_MODE);
      if(pid = fork()>0) {
          readfd = open(FIFO1, O_RDONLY, 0);
          writefd = open(FIFO2, O_wDONLY, 0);
          write(writefd, "hello world!\n", 12);
          read(readfd, line1, length);
          printf("%s", line1);
      }//parent
      else {
          readfd = open(FIFO2, O_RDONLY, 0);
          writefd = open(FIFO1, O_wDONLY, 0);
          write(writefd, "hello world!\n", 12);
          read(readfd, line2, length);
          printf("%s", line2);
      }//child

可以看到這和半雙工管道很像,可以把理解成存儲在Unix系統中的管道。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容