Linux 進程間通信 有名管道(fifo)


有名管道特點

1)無名管道只能用於具有親緣關系的進程之間,這就限制了無名管道的使用范圍

2)有名管道可以使互不相關的兩個進程互相通信。

3)有名管道可以通過路徑名來指出,並且在文件系統中可見,但內容存放在內存中

4)進程通過文件IO來操作有名管道

5)有名管道遵循先進先出規則

6)不支持如lseek() 操作

 

注意
以O_WRONLY打開管道,讀阻塞
以O_RDWR打開管道,當管道中沒有數據,讀阻塞
//當進程用open打開有名管道用只讀方式打開的話,則返回的文件描述符就代表管道的讀端

創建有名管道

  int mkfifo(const char *filename, mode_t  mode)

  參數:filename 有名管道文件名(包括路徑);mode 權限(讀寫0666)

  成功返回 0 ,失敗返回-1 並設置 errno 號 errno == EEXIST 時表示該有名管道已經存在

對有名管道的操作是通過文件IO 中的open read write 等操作的

 

例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>


int main(int argc, const char *argv[])
{
    char buf[50] = {0};
    if(mkfifo("./fifo",0777) != 0 ) //在當前路徑下(運行程序所在的路徑)創建有名管道,有名管道權限讀寫執行
    {
        if(errno == EEXIST) //當該有名管道存在時,提示下
        {
            printf("File exists\n");
        }
        else
        {
            perror("mkfifo fail ");
            exit(1);
        }
    }

    int fd;
    fd = open("./fifo",O_RDWR);//讀寫方式打開,使用文件IO 操作有名管道
    if(fd < 0)
    {
        perror("open fifo fail: ");
        exit(1);
    }
    write(fd,"1234567",7);
    read(fd,buf,7);
    printf("%s\n",buf);
    return 0;
}

測試:

 

 例子:通過有名管道讓兩個進程實現文件的復制

 

(1)讀取文件寫入有名管道中

/* 功能:實現在終端上輸入獲取文件名,讀取文件內容,寫到有名管道fifo中
 * */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
    char buf[50] = {0};
    if(mkfifo("./fifo",0777) != 0 ) //創建有名管道
    {
        if(errno == EEXIST)
        {
            printf("File exists\n");
        }
        else
        {
            perror("mkfifo fail ");
            exit(1);
        }
    }
    int fd_fifo,fd_file;
    fd_fifo = open("./fifo",O_WRONLY);//只寫方式打開,管道描述符
    if(fd_fifo < 0)
    {
        perror("open fifo fail: ");
        exit(1);
    }
    fd_file = open(argv[1],O_RDONLY);//只讀方式打開,源文件進行復制到管道中
    if(fd_file < 0)
    {
        perror("open source fail ");
        exit(1);
    }

    //循環讀取文件內容
    ssize_t size;
    while(1)
    {
        size = read(fd_file,buf,50); //文件中讀取數據,返回讀取到多少數據
        if(size <= 0)
        {
            break;
        }
        write(fd_fifo,buf,size);
    }
    close(fd_file);//關閉讀的源文件
    close(fd_fifo);
    return 0;
}

(2)讀取有名管道中的數據,寫入文件中實現復制

/* 功能:實現在有名管道中讀取數據,寫到文件中
 * */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
    char buf[50] = {0};
    if(mkfifo("./fifo",0777) != 0 ) //創建有名管道
    {
        if(errno == EEXIST) //有名管道存在的情況
        {
            printf("File exists\n");
        }
        else
        {
            perror("mkfifo fail ");
            exit(1);
        }
    }
    
    int fd_fifo,fd_file;  //此處fd_r是指有名管道,在有名管道中讀取數據,寫到文件中

    fd_fifo = open("./fifo",O_RDONLY);//讀方式打開
    if(fd_fifo < 0)
    {
        perror("open fifo fail: ");
        exit(1);
    }
    
    fd_file = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666);//把從有名管道中讀取的數據,寫到文件中,只讀,沒有創建,清空打開
    if(fd_file < 0)
    {
        perror("fd_w open fail ");
        exit(1);
    }
    //fifo 中循環讀取數據,然后寫到文件中
    ssize_t size;
    while(1)
    {
        size = read(fd_fifo,buf,50); //讀有名管道內容,返回讀取多少個數據
        if(size <= 0)
        {
            break;
        }
        write(fd_file,buf,size); //寫入文件中
    }
    close(fd_fifo);
    close(fd_file);
    return 0;
}

測試:此時要打開兩個終端讓兩個進程進行通信,一個執行寫操作,一個執行都操作(有名管道中有數據才可以讀,且管道數據內容存在內存中)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM