命名管道(FIFO)

FIFO

FIFO Concept

管道的一個不足之處是沒有名字,因此,只能用於具有親緣關係的進程間通信,在命名管道(named pipe或FIFO)提出後,該限制得到了克服。

  • FIFO不同於管道之處在於它提供一個路徑名(pathname)與之關聯,以FIFO的文件形式存儲於文件系統中
  • 命名管道是一個設備文件,因此,即使進程與創建FIFO的進程不存在親緣關係,只要可以訪問該路徑,就能夠通過FIFO相互通信
  • FIFO(first input first output)總是按照先進先出的原則工作,第一個被寫入的數據將首先從管道中讀出
  • 命名管道存儲於硬盤,使用前要先打開(open())
  • 命名管道也被稱爲FIFO文件,它是一種特殊類型的文件,它在文件系統中以文件名的形式存在,但是它的行爲卻和之前所講的沒有名字的管道(匿名管道)類似。
FIFO Create
  • 在Shell下交互的創建一個命名管道
    這裏寫圖片描述
  • 在程序中使用系統函數創建命名管道
//頭文件
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 //函數原型:
int mknod(const char *pathname, mode_t mode, dev_t dev);
int mkfifo(const char *pathname, mode_t mode);//建議儘量使用這個函數
//兩個函數的pathname和mode參數含義相同
//pathname-->命名管道的全路徑名
//mode-->創建命名管道的模式,指定文件的讀取權限
//dev-->設備值,只在創建設備文件是纔會用到
//返回值:成功(0);失敗(-1)
FIFO Using Process
  • 創建FIFO(FIFO Create)
  • 打開FIFO(open())

    O_RDWR(讀寫方式):不會導致阻塞
    O_RDONLY(只讀方式):調用open()函數的進程將會被阻塞,直到有寫方打開管道
    O_WRONLY(寫方式):也會阻塞,直到有讀方打開管道

  • 使用FIFO(與管道基本相同)

//FIFO write
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>
#define PATHNAME "/home/wgb/code/FIFO/FIFO/file.tmp"//注意路徑的設置
#define MAX_SIZE 100

int main()
{
    int ret = mkfifo(PATHNAME,S_IFIFO|0666);//創建管道
    if(ret<0)
    {
        printf("mkfifo error\n");
        printf("error num:%d error info:%s\n",ret,strerror(ret));
        return -1;
    }
    int fd = open(PATHNAME,O_WRONLY);//打開管道
    if(fd<0)
    {
        printf("open error\n");
        printf("error num:%d error info:%s\n",fd,strerror(fd));
        return -2;
    }
    char buf[MAX_SIZE];
    memset(buf,'\0',sizeof(buf));
    while(1)
    {
        scanf("%s",buf);
        int ret = write(fd,buf,strlen(buf)+1);//寫
        if(ret<0)
        {
            printf("write error\n");
            printf("error num:%d error info:%s\n",fd,strerror(fd));
            break;
        }
        if(strncmp(buf,"exit",4)==0)//輸入exit退出
            break;
    }
    close(fd);
    return 0;
}
//FIFO read:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>

#define PATHNAME "/home/wgb/code/FIFO/FIFO/file.tmp"
#define MAX_SIZE 100

int main()
{
    int fd = open(PATHNAME,O_RDONLY);//打開管道
    if(fd<0)
    {
        printf("open error\n");
        printf("error num:%d error info:%s\n",fd,strerror(fd));
        return -2;
    }
    char buf[MAX_SIZE];
    memset(buf,'\0',sizeof(buf));
    while(1)
    {
        int ret = read(fd,buf,sizeof(buf));//讀取
        if(ret<0)
        {
            printf("open error\n");
            printf("error num:%d error info:%s\n",fd,strerror(fd));
            break;
        }
        printf("%s\n",buf);
        if(strncmp(buf,"exit",4)==0)//退出
            break;
    }
    close(fd);//打開就要關閉
    return 0;
}

這裏寫圖片描述

總結

文件系統中的路徑名是全局的,各進程都可以訪問,因此可以用文件系統中的路徑名來標識一個IPC通道。
由於Linux中所有的事物都可被視爲文文件,所以對命名管道的使用也就變得與文件操作非常的統一,也使它的使用非常方便,同時我們也可以像平常的文件名一樣在命令中使用。
mkfifo函數的作用用是在文文件系統中創建一一個文文件,該文文件用用於提供FIFO功能,即命名管道。
前邊講的那些管道都沒有名字,因此它們被稱爲匿名管道,或簡稱管道。對文件系統來說,匿名管道是不可見的,它的作用僅限於在父進程和子進程兩個進程間進行通信。而命名管道是一個可見的文件,因此,它可以用於任何兩個進程之間的通信,不管這兩個進程是不是父子進程,也不管這兩個進程之間有沒有關係。

發佈了66 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章