有名管道特点:
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 "); } 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 ",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 "); } 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 "); } 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; }
测试:此时要打开两个终端让两个进程进行通信,一个执行写操作,一个执行都操作(有名管道中有数据才可以读,且管道数据内容存在内存中)