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