Linux處理序間通訊(IPC)之二——具名管道(FIFO)

來源:互聯網
上載者:User
1 具名管道(FIFO)

      經過前文《Linux處理序間通訊(IPC)之一——管道》介紹管道,但是管道應用的一個重大缺陷就是沒有名字,因此只能用於親緣進程之間的通訊。後來從管道為基礎提出具名管道(named pipe,FIFO)的概念,該限制得到了克服。FIFO不同於管道之處在於它提供一個路徑名與之關聯,以FIFO的檔案形式存在於檔案系統中。這樣,即使與FIFO的建立進程不存在親緣關係的進程,只要可以訪問該路徑,就能夠彼此通過FIFO相互連信(能夠訪問該路徑的進程以及FIFO的建立進程之間),因此,通過FIFO不相關的進程也能交換資料。值得注意的是,FIFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀總是從開始處返回資料,對它們的寫則把資料添加到末尾。它們不支援諸如lseek()等檔案定位操作。

2 具名管道的建立
#include <sys/types.h>#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);
     該函數經建立一個FIFO,FIFO在檔案系統中表現為一個檔案(該檔案為fifo類型檔案),檔案的路徑由參數pathname指定;第二個參數mode和系統調用open函數中的mode是一樣的。如果pathname路徑下的檔案已經存在,則mkfifo返回-1,errono將會返回EEXIST。3 具名管道操作

     FIFO在檔案系統中表現為一個檔案,大部分的系統檔案調用都可以用在FIFO上面,比如:read,open,write,close,unlink,stat等函數。但是seek等函數不能對FIFO調用。

    可以調用open開啟FIFO,請注意以下方面:

1、當以阻塞(未指定O_NONBLOCK)方式唯讀開啟FIFO的時候,則將會被阻塞,知道有其他進程以寫方式開啟該FIFO。

2、類似的,當以阻塞(未指定O_NONBLOCK)方式唯寫開啟FIFO的時候,則將會被阻塞,知道有其他進程以讀方式開啟該FIFO。

3、當以非阻塞方式(指定O_NONBLOCK)方式唯讀開啟FIFO的時候,則立即返回-1,其errno是ENXIO。

    在上文《Linux處理序間通訊(IPC)之一——管道》提到:如果寫入管道的資料量小於等於PIPE_BUF,則系統保證write為原子操作,多個進程同時寫管道,將不會出現穿插;如果寫入資料量大於PIPE_BUF,則系統將不保證write為原子操作,多個進程同時寫管道,則將有可能會穿插寫入。這個規則在具名管道中繼續適用。4 應用執行個體

     本例為一個client-server模式,伺服器端將會建立一個聞名fifo檔案(本例中為“/tmp/server”),並讀取該fifo檔案。用戶端則開啟該fifo檔案,並把其請求寫入該FIFO檔案。伺服器端讀取該命令並執行之。

     伺服器端的代碼為:

#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>struct fifo_cmd{pid_t child_pid;char cmd[100];};int main(void){int fd;struct fifo_cmd cmd;int err;int n;if((err = mkfifo("/tmp/server", 0777)) < 0){if(errno != EEXIST){perror("mkfido fail: ");exit(-1);}}if((fd = open("/tmp/server", O_RDONLY)) < 0){perror("open fail: ");exit(-1);}while(1){if((n = read(fd, &cmd, sizeof(cmd))) < 0){perror("read fail: ");exit(-1);}if(n > 0){printf("command from %d: %s/n", cmd.child_pid, cmd.cmd);}sleep(1);}}

請把這個代碼編譯成server。

     用戶端代碼如下:

#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <string.h>struct fifo_cmd{pid_t pid;char cmd[100];};int main(int argc, char* argv[]){int fd;struct fifo_cmd cmd;if((fd = open("/tmp/server", O_WRONLY)) < 0){perror("open fail: ");exit(-1);}cmd.pid = getpid();while(1){printf("%%: ");fgets(cmd.cmd, sizeof(cmd.cmd), stdin);cmd.cmd[strlen(cmd.cmd) - 1] = 0;if(write(fd, &cmd, sizeof(cmd)) < 0){perror("write fail: ");exit(-1);}}}

請把用戶端代碼編譯成client。

     測試時我們可以啟動多個client,我們將會看到client發生命令將會在伺服器端執行之。

5 總結

     與管道相比,FIFO最大的特點就是其在檔案系統中有fifo檔案存在,這樣就可以做到處理序間通訊。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.