管道只能用於親緣關系之間的通信,而FIFO中,只要可以訪問路徑,就可以進行通信。
FIFO按照先進先出的原則進行通信,第一個被寫入的數據首先從管道中讀出。
創建命名管道的系統函數有兩個: mknod和mkfifo。兩個函數均定義在頭文件sys/stat.h,函數原型如下:
#include <sys/types.h>
#include <sys/stat.h>
int mknod(const char *path,mode_t mod,dev_t dev);
int mkfifo(const char *path,mode_t mode);
函數mknod參數中path為創建的命名管道的全路徑名: mod為創建的命名管道的模式,指明其存取權限; dev為設備值,該值取決於文件創建的種類,它只在創建設備文件時才會用到。這兩個函數調用成功都返回0,失敗都返回- 1。使用mknod函數創建了一個命名管道:
umask(0);
if (mknod("/tmp/fifo",S_IFIFO | 0666) == -1)
{
perror("mkfifo error");
exit(1);
}
函數mkfifo前兩個參數的含義和mknod相同。
umask(0);
if (mkfifo("/tmp/fifo",S_IFIFO|0666) == -1)
{
perror("mkfifo error!");
exit(1);
}
“S_IFIFO|0666”指明創建一個命名管道且存取權限為0666,即創建者、與創建者同組的用戶、其他用戶對該命名管道的訪問權限都是可讀可寫( 這需要注意umask對生成的管道文件權限的響)。
調用open()打開命名管道的進程可能會被阻塞。但如果同時用讀寫方式( O_RDWR)打開,則一定不會導致阻塞;如果以只讀方式( O_RDONLY)打開,則調用open()函數的進程將會被阻塞直到有寫方打開管道;同樣以寫方式( O_WRONLY)打開也會阻塞直到有讀方式打開管道。
對文件系統來說,匿名管道是不可見的,它的作用僅限於在父進程和子進程兩個進程間進行通信。而命名管道是一個可見的文件,因此,它可以用於任何兩個進程之間的通信,不管這兩個進程是不是父子進程,也不管這兩個進程之間有沒有關系。
fifo read端:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #define _PATH_ "/tmp/file.tmp" #define _SIZE_ 100 int main() { int fd = open(_PATH_, O_RDONLY); if (fd < 0){ printf("open file error!\n"); return 1; } char buf[_SIZE_]; memset(buf, '\0', sizeof(buf)); while (1){ int ret = read(fd, buf, sizeof(buf)); if (ret <= 0)//error or end of file { printf("read end or error!\n"); break; } printf("%s\n", buf); if (strncmp(buf, "quit", 4) == 0){ break; } } close(fd); return 0; }fifo write端:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #define _PATH_ "/tmp/file.tmp" #define _SIZE_ 100 int main() { int ret = mkfifo(_PATH_, 0666|S_IFIFO); if (ret == -1){ printf("mkfifo error\n"); return 1; } int fd = open(_PATH_, O_WRONLY); if (fd < 0){ printf("open error\n"); } char buf[_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"); break; } if (strncmp(buf, "quit", 4) == 0){ break; } } close(fd); return 0; }