国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Linux > 正文

linux進程間通信-有名管道(FIFO)

2024-06-28 13:23:39
字體:
來源:轉載
供稿:網友
linux進程間通信-有名管道(FIFO) Posted on 2014-10-21 11:00 fangsh 閱讀(...) 評論(...) 編輯 收藏有名管道(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的路徑名,而不是正常的文件。(如:constchar*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字節,系統就可以確保數據決不會交錯在一起。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永登县| 洛隆县| 昌江| 阿坝县| 海阳市| 霍林郭勒市| 宣武区| 泰安市| 兴仁县| 白玉县| 会理县| 桐梓县| 全州县| 塔城市| 会昌县| 嫩江县| 广灵县| 门头沟区| 自治县| 洞口县| 上虞市| 镇原县| 喀喇沁旗| 合江县| 阿勒泰市| 嵊泗县| 资中县| 来凤县| 青铜峡市| 禹城市| 翼城县| 历史| 和田县| 荥阳市| 福泉市| 天峻县| 土默特左旗| 昌江| 青川县| 双牌县| 大冶市|