有名管道特點:
1)無名管道只能用於具有親緣關系的進程之間,這就限制了無名管道的使用范圍
2)有名管道可以使互不相關的兩個進程互相通信。
3)有名管道可以通過路徑名來指出,並且在文件系統中可見,但內容存放在內存中。
4)進程通過文件IO來操作有名管道
5)有名管道遵循先進先出規則
6)不支持如lseek() 操作
注意:
以O_WRONLY打開管道,讀阻塞
以O_RDWR打開管道,當管道中沒有數據,讀阻塞
//當進程用open打開有名管道用只讀方式打開的話,則返回的文件描述符就代表管道的讀端
創建有名管道:
int mkfifo(const char *filename, mode_t mode)
參數:filename 有名管道文件名(包括路徑);mode 權限(讀寫0666)
成功返回 0 ,失敗返回-1 並設置 errno 號 errno == EEXIST 時表示該有名管道已經存在
對有名管道的操作是通過文件IO 中的open read write 等操作的
例子:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> int main(int argc, const char *argv[]) { char buf[50] = {0}; if(mkfifo("./fifo",0777) != 0 ) //在當前路徑下(運行程序所在的路徑)創建有名管道,有名管道權限讀寫執行 { if(errno == EEXIST) //當該有名管道存在時,提示下 { printf("File exists\n"); } else { perror("mkfifo fail "); exit(1); } } int fd; fd = open("./fifo",O_RDWR);//讀寫方式打開,使用文件IO 操作有名管道 if(fd < 0) { perror("open fifo fail: "); exit(1); } write(fd,"1234567",7); read(fd,buf,7); printf("%s\n",buf); return 0; }
測試:
例子:通過有名管道讓兩個進程實現文件的復制
(1)讀取文件寫入有名管道中
/* 功能:實現在終端上輸入獲取文件名,讀取文件內容,寫到有名管道fifo中 * */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> int main(int argc, const char *argv[]) { char buf[50] = {0}; if(mkfifo("./fifo",0777) != 0 ) //創建有名管道 { if(errno == EEXIST) { printf("File exists\n"); } else { perror("mkfifo fail "); exit(1); } } int fd_fifo,fd_file; fd_fifo = open("./fifo",O_WRONLY);//只寫方式打開,管道描述符 if(fd_fifo < 0) { perror("open fifo fail: "); exit(1); } fd_file = open(argv[1],O_RDONLY);//只讀方式打開,源文件進行復制到管道中 if(fd_file < 0) { perror("open source fail "); exit(1); } //循環讀取文件內容 ssize_t size; while(1) { size = read(fd_file,buf,50); //文件中讀取數據,返回讀取到多少數據 if(size <= 0) { break; } write(fd_fifo,buf,size); } close(fd_file);//關閉讀的源文件 close(fd_fifo); return 0; }
(2)讀取有名管道中的數據,寫入文件中實現復制
/* 功能:實現在有名管道中讀取數據,寫到文件中 * */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> int main(int argc, const char *argv[]) { char buf[50] = {0}; if(mkfifo("./fifo",0777) != 0 ) //創建有名管道 { if(errno == EEXIST) //有名管道存在的情況 { printf("File exists\n"); } else { perror("mkfifo fail "); exit(1); } } int fd_fifo,fd_file; //此處fd_r是指有名管道,在有名管道中讀取數據,寫到文件中 fd_fifo = open("./fifo",O_RDONLY);//讀方式打開 if(fd_fifo < 0) { perror("open fifo fail: "); exit(1); } fd_file = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666);//把從有名管道中讀取的數據,寫到文件中,只讀,沒有創建,清空打開 if(fd_file < 0) { perror("fd_w open fail "); exit(1); } //fifo 中循環讀取數據,然后寫到文件中 ssize_t size; while(1) { size = read(fd_fifo,buf,50); //讀有名管道內容,返回讀取多少個數據 if(size <= 0) { break; } write(fd_file,buf,size); //寫入文件中 } close(fd_fifo); close(fd_file); return 0; }
測試:此時要打開兩個終端讓兩個進程進行通信,一個執行寫操作,一個執行都操作(有名管道中有數據才可以讀,且管道數據內容存在內存中)