int mkfifo(const char *pathname, mode_t mode);
int mknod(const char *pathname, mode_t mode, dev_t dev);
管道的一個不足之處是沒有名字,因此,只能用於具有親緣關系的進程間通信。
在有名管道(named pipe或FIFO)提出來之后,該限制得到了克服。FIFO不同於管道之處在於它提供一個路徑與之關聯,
以FIFO的文件形式存儲於文件系統中。有名管道是一個設備文件。因此,即使進程與創建FIFO的進程不存在親緣關系,
只要可以訪問該路徑,就能夠通過FIFO相互通信。值得注意的是,FIFO(first in first out)總是按照先進先出的原則工作,
第一個被寫入的數據將首先從管道中讀出。
有名管道的創建與讀寫
LINUX下有兩種方式創建有名管道。一是在Shell下交互地建立一個有名管道,二是在程序中使用系統函數建立有名管道。
shell方式下可使用mknod或mkfifo命令,下面命令使用mknod創建一個有名管道:
mknod namedpipe
----------------------------------------------------------------
創建有名管道的函數有兩個:mknod和mkfifo
int mkfifo(const char *pathname, mode_t mode);
int mknod(const char *pathname, mode_t mode, dev_t dev);
函數mknod參數中path為創建的有名管道的全路徑名;mod為創建的有名管道的模式,指明其存取權限;dev為設備值,該值取決於文件創建的種類,
它只在創建設備文件時才會用到。
umask(0);
if (mknod("/tmp/fifo", S_IFIFO|0666, 0) == -1)
{
perror("mknod error!");
exit(1);
}
umask(0);
if (mkfifo("/tmp/fifo", S_IFIFO|0666) == -1)
{
perror("mkfifo error!");
exit(1);
}
S_IFIFO|0666 指明創建一個有名管道且存取權限為0666,即創建者、與創建者同組的用戶、其他用戶對該有名管道的 訪問權限 都是 可讀可寫。
有名管道創建后就可以使用了,有名管道和管道的使用方法基本是相同的。只是使用有名管道時,必須先調用open將其打開。因為有名管道
是一個存在於硬盤上的文件,而管道是存在於內存中的特殊文件。
需要注意的是,調用open打開有名管道的進程可能會被阻塞。但如果同時用讀寫方式(O_RDWR)打開,則一定不會導致阻塞;如果以只讀方式
(O_RDONLY)打開,則調用open函數的進程將會被阻塞直到有寫方式打開管道;同樣以寫方式(O_WRONLY)打開也會阻塞直到有讀方式打開管道。
實例:
寫端:
#include <stdio.h> #include <unistd.h> #include <strings.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>
#define FIFO_NAME "testfifo"
int main(int argc, char* argv[]) { int fd; char buf[] = "yyyyyyy"; mkfifo(FIFO_NAME, S_IFIFO|0666); fd = open(FIFO_NAME, O_WRONLY); write(fd, buf, strlen(buf)+1); close(fd);
unlink(FIFO_NAME);//刪除管道文件
sleep(1);
return 0; }
讀端:
#include <stdio.h> #include <unistd.h> #include <strings.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>
#define FIFO_NAME "testfifo"
#define BUF_SIZE 1024
int main(int argc, char* argv[]) { int fd; char buf[BUF_SIZE]; fd = open(FIFO_NAME, O_RDONLY); read(fd, buf, BUF_SIZE); printf("%s\n", buf); close(fd); return 0; }