天天看點

IPC-命名管道(FIFO)

學習了匿名管道,我們知道它的一個不足之處就是沒有名字,是以隻能在兩個相關程序之間使用,而且這兩個相關程序要有一個公共祖先程序。那如果兩個程序沒有血緣關系,也想進行通信該怎麼辦呢?方法就是命名管道。

命名管道(FIFO):

  • 突破了匿名管道隻能用于具有血緣關系間的程序通信,它可以使兩個互不相幹的程序彼此通信。
  • 提供了一個路徑名與之相關聯,以FIFO檔案形式存儲在檔案系統中。
  • 與匿名管道相同是,命名管道也遵守遵守先進先出的規則,第一個被寫入的資料總是首先從管道被讀出。
  • FIFO不同于匿名管道之處在于它提供一個路徑名與之關聯,以FIFO檔案形式存在檔案系統中。FIFO是一個裝置檔案,是以,隻要可以通路該路徑,就能通過FIFO互相通信。

命名管道的建立:

Linux下有兩種建立方式建立命名管道。一是在shell下互動的建立一個命名管道,而是使用系統函數建立命名管道。

Shell方式下可使用mkfifo和mkdon指令來創立命名管道:mkdon namepipi

建立命名管道的系統函數有兩個mkdon()和mkfifo()。

兩函數定義:

#include<sys/stat.h>
int mkfifo(const char *path,mode_t mode);
int mkdon(const char *path,mode_t mode,dev_t dev);
           

//可以指定路徑,名字,打開方式。

參數:path為建立的命名管道的全路徑名,mode為建立的命名管道的模式,指的是其存儲權限。modon獨有的dev為裝置值,隻有建立裝置檔案時才需要dev。

傳回值:當調用成功時傳回0,調用失敗時傳回-1;

當我們用mkfifo或者mkdon建立FIFO時,要用open打開它。确實,正常的檔案I/O函數(如close、read、write和unlink)都需要FIFO。

當我們open一個FIFO時,會産生如下影響:

  • 阻塞打開(沒有指定O_NONBLOCK)。對于讀,隻讀open阻塞,直到某個程序以寫而打開FIFO為止,如果有資料,讀取完管道裡面資料。隻寫open,阻塞到某程序以讀方式打開FIFO。
  • 非阻塞打開(指定O_NONBLOCK),則隻讀open立即傳回。如果沒有程序以讀打開FIFO,那麼隻寫open傳回-1。

    若write一個沒有以讀方式打開的FIFO時,将會産生信号SIGPIPE。若FIFO最後一個寫程序關閉了該FIFO,則将為以讀打開該FIFO的程序産生一個檔案結束标志。

代碼執行個體:

這裡是test中寫入i am test 然後通過命名管道receive讀取并列印。

test.c

/*************************************************************************

    > File Name: test.c

    > Author: 

    > Mail: 

    > Created Time: Mon 22 May 2017 04:47:33 AM PDT

 ************************************************************************/

#include<stdio.h>

#include<unistd.h>

#include<sys/types.h>

#include<stdlib.h>

#include<string.h>

#include<fcntl.h>

int main()

{

    if(mkfifo("tmp",0666)==-1)

    {

        printf("myfifo error!");

        exit(1);

    }

    else

    {

        int n=open("tmp",O_WRONLY);

        if(n==-1)

        {

            printf("open error!\n");

            exit(1);

        }

        else

        {

            char *mesg="i am test!";

            write(n,mesg,strlen(mesg)+1);

        }

    }

    return 0;

}
           

receive.c中

/*************************************************************************

    > File Name: revive.c

    > Author: 

    > Mail: 

    > Created Time: Mon 22 May 2017 07:28:57 AM PDT

 ************************************************************************/

#include<stdio.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<stdlib.h>

#include<fcntl.h>

int main()

{

    int fd=open("tmp",O_RDONLY);

    if(fd==-1)

    {

        printf("receive error!\n ");

        exit(1);

    }

    else

    {

        char mesg[100];



       ssize_t s= read(fd,mesg,sizeof(mesg));

       mesg[s-1]='\0';

       printf("%s\n",mesg);

    }

    return 0;

}