linux處理序間通訊-有名管道(FIFO)

來源:互聯網
上載者:User

標籤:style   blog   color   io   os   ar   使用   for   sp   

有名管道(FIFO)

具名管道也被稱為FIFO檔案,是一種特殊的檔案。由於linux所有的事物都可以被視為檔案,所以對具名管道的使用也就變得與檔案操作非常統一。

(1)建立具名管道

 用如下兩個函數中的其中一個,可以建立具名管道。

 

#include <sys/types.h>#include <sys/stat.h>int mkfifo(const char *filename, mode_t mode);int mknod(const char *filename, mode_t mode | S_IFIFO, (dev_t)0);

filname是指檔案名稱,而mode是指定檔案的讀寫權限。mknod是比較老的函數,而使用mkfifo函數更加簡單和規範,所以建議用mkfifo。

 

open(const char *path, O_RDONLY);//1open(const char *path, O_RDONLY | O_NONBLOCK);//2open(const char *path, O_WRONLY);//3open(const char *path, O_WRONLY | O_NONBLOCK);//4

 

(2)開啟具名管道

和開啟其他檔案一樣,可以用open來開啟。通常有四種方法:

有兩點要注意:

1、就是程式不能以O_RDWR(讀寫)模式開啟FIFO檔案進行讀寫操作,而其行為也未明確定義,因為如一個管道以讀/寫方式開啟,進程就會讀回自己的輸出,同時我們通常使用FIFO只是為了單向的資料傳遞。

2、就是傳遞給open調用的是FIFO的路徑名,而不是正常的檔案。(如:const char *fifo_name = "/tmp/my_fifo"; )

3、第二個參數中的選項O_NONBLOCK,選項O_NONBLOCK表示非阻塞,加上這個選項後,表示open調用是非阻塞的,如果沒有這個選項,則表示open調用是阻塞的。

(3)阻塞問題

對於以唯讀方式(O_RDONLY)開啟的FIFO檔案,如果open調用是阻塞的(即第二個參數為O_RDONLY),除非有一個進程以寫方式開啟同一個FIFO,否則它不會返回;如果open調用是非阻塞的的(即第二個參數為O_RDONLY | O_NONBLOCK),則即使沒有其他進程以寫方式開啟同一個FIFO檔案,open調用將成功並立即返回。

對於以唯寫方式(O_WRONLY)開啟的FIFO檔案,如果open調用是阻塞的(即第二個參數為O_WRONLY),open調用將被阻塞,直到有一個進程以唯讀方式開啟同一個FIFO檔案為止;如果open調用是非阻塞的(即第二個參數為O_WRONLY | O_NONBLOCK),open總會立即返回,但如果沒有其他進程以唯讀方式開啟同一個FIFO檔案,open調用將返回-1,並且FIFO也不會被開啟。

(4)使用FIFO實現進程間的通訊

管道的寫入端從一個檔案讀出資料,然後寫入寫管道。管道的讀取端從管道讀出後寫到檔案中。

寫入端代碼:fifowrite.c

 

#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <string.h> int main(){    const char *fifo_name = "/tmp/my_fifo";    int pipe_fd = -1;    int data_fd = -1;    int res = 0;    const int open_mode = O_WRONLY;    int bytes_sent = 0;    char buffer[PIPE_BUF + 1];    int bytes_read = 0;
if(access(fifo_name, F_OK) == -1) { printf ("Create the fifo pipe.\n"); res = mkfifo(fifo_name, 0777);
if(res != 0) { fprintf(stderr, "Could not create fifo %s\n", fifo_name); exit(EXIT_FAILURE); } } printf("Process %d opening FIFO O_WRONLY\n", getpid()); pipe_fd = open(fifo_name, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd); if(pipe_fd != -1) { bytes_read = 0; data_fd = open("Data.txt", O_RDONLY); if (data_fd == -1) { close(pipe_fd); fprintf (stderr, "Open file[Data.txt] failed\n"); return -1; } bytes_read = read(data_fd, buffer, PIPE_BUF); buffer[bytes_read] = ‘\0‘; while(bytes_read > 0) { res = write(pipe_fd, buffer, bytes_read); if(res == -1) { fprintf(stderr, "Write error on pipe\n"); exit(EXIT_FAILURE); } bytes_sent += res; bytes_read = read(data_fd, buffer, PIPE_BUF); buffer[bytes_read] = ‘\0‘; } close(pipe_fd); close(data_fd); } else exit(EXIT_FAILURE); printf("Process %d finished\n", getpid()); exit(EXIT_SUCCESS);}

管道讀取端: fiforead.c

#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <limits.h>#include <string.h>int main(){    const char *fifo_name = "/tmp/my_fifo";    int pipe_fd = -1;    int data_fd = -1;    int res = 0;    int open_mode = O_RDONLY;    char buffer[PIPE_BUF + 1];    int bytes_read = 0;    int bytes_write = 0;    memset(buffer, ‘\0‘, sizeof(buffer));    printf("Process %d opening FIFO O_RDONLY\n", getpid());    pipe_fd = open(fifo_name, open_mode);    data_fd = open("DataFormFIFO.txt", O_WRONLY|O_CREAT, 0644);    

if (data_fd == -1) { fprintf(stderr, "Open file[DataFormFIFO.txt] failed\n"); close(pipe_fd); return -1; } printf("Process %d result %d\n",getpid(), pipe_fd); if(pipe_fd != -1) { do { res = read(pipe_fd, buffer, PIPE_BUF); bytes_write = write(data_fd, buffer, res); bytes_read += res; }while(res > 0); close(pipe_fd); close(data_fd); } else exit(EXIT_FAILURE); printf("Process %d finished, %d bytes read\n", getpid(), bytes_read); exit(EXIT_SUCCESS);}

 

(5)具名管道的安全問題

有一種情況是:一個FIFO檔案,有多個進程同時向同一個FIFO檔案寫資料,而只有一個讀FIFO進程在同一個FIFO檔案中讀取資料時,會發生資料區塊的相互交錯。不同進程向一個FIFO讀進程發送資料是很普通的情況。這個問題的解決方案,就是讓寫操作的原子化。系統規定:在一個以O_WRONLY(即阻塞方式)開啟的FIFO中, 如果寫入的資料長度小於等待PIPE_BUF,那麼或者寫入全部位元組,或者一個位元組都不寫入。如果所有的寫請求都是發往一個阻塞的FIFO的,並且每個寫記請求的資料長度小於等於PIPE_BUF位元組,系統就可以確保資料決不會交錯在一起。

linux處理序間通訊-有名管道(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.