管道的一個不足之處是沒有名字,因此只能在具有親緣關係的進程之間通信。而“有名管道”與此不同,它提供了一個路徑名與之關聯,作爲一個設備文件存在,即使無親緣關係的進程之間,只要能訪問該路徑,也可以通過FIFO進行通信。FIFO總是按照先進先出的原則工作,第一個被寫入的數據將首先從管道中讀出。
函數原型:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *path,mode_t mode);
path爲創建有名管道的路徑名;mode爲創建有名管道的模式,指明其存取權限。函數調用成功返回0,失敗返回-1。
使用一個存在的有名管道之前,需要用open()將其打開。因爲有名管道是一個存在於硬盤上的文件,而管道是存在於內存中的特殊文件。
以下程序演示有名管道在無親緣關係的進程之間如何通信。
//procwriter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "myfifo"
#define BUF_SIZE 1024
int main(void)
{
int fd;
char buf[BUF_SIZE] = "Hello procwrite, I come from process named procread!";
umask(0);
//指明創建一個有名管道且存取權限爲0666,即創建者、與創建者同組的用戶、其他用戶對該有名管道的訪問權限都是可讀可寫
if (mkfifo (FIFO_NAME, S_IFIFO | 0666) == -1)
{
perror ("mkfifo error!");
exit (1);
}
if((fd = open (FIFO_NAME, O_WRONLY) ) == -1)/*以寫方式打開FIFO*/
{
perror ("fopen error!");
exit (1);
}
write (fd, buf, strlen(buf)+1); /*向FIFO寫數據*/
close (fd);
exit (0);
}
procreader.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#define FIFO_NAME "myfifo"
#define BUF_SIZE 1024
int main(void)
{
int fd;
char buf[BUF_SIZE];
umask (0);
fd = open(FIFO_NAME, O_RDONLY);
read (fd, buf, BUF_SIZE);
printf ("Read content: %s\n", buf);
close (fd);
exit (0);
}
首先運行procwrite(運行後處於阻塞狀態),打開另一個終端運行程序procread。結果如下: