匿名管道(pipe)和命名管道(mkfifo) |
您所在的位置:网站首页 › 网名与命名缘由的区别 › 匿名管道(pipe)和命名管道(mkfifo) |
匿名管道(pipe)和命名管道(mkfifo) 进程间通信必须通过内核提供的通道。 1、匿名管道匿名管道通过打开的文件描述符来标识的。——用于具有亲缘关系间进程之间的通信。 int pipe(int fds[2]);//返回值0表示成功,-1表示失败 fd[0]:读 fd[1]:写 写数据时要关闭读端 读数据时要关闭写端 2、命名管道命名管道借助于文件系统实现,文件系统中的路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道。——用于具有非亲缘关系间进程之间的通信。 命名管道的打开规则: 如果当前打开操作是为读而打开FIFO时 O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO O_NONBLOCK enable:立刻返回成功 如果当前打开操作是为写而打开FIFO时 O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO O_NONBLOCK enable:立刻返回失败,错误码为ENXIO 需要注意的是打开的文件描述符默认是阻塞的. 管道的创建 管道文件大小为0,没有亲缘关系的文件也能通过管道名,来取到该管道中的缓存。 //创建管道文件 int mkfifo(const char *name,mode_t mode) //打开管道文件 int fd=open(name,O_RDONLY);读 int fd=open(name,O_WRONLY);写 3、匿名管道与命名管道的区别:匿名管道是由pipe函数创建 并打开的 命名管道是由mkfifo函数创建 的 ,打开用open 命名管道和匿名管道唯一的区别就是在创建的打开,一旦这些工作完成后,它们有相同的意义。 匿名管道实例1: /* * 父进程通过命令行的方式输入内容(argv[1])写入管道 * 子进程从管道中读取数据并输出到标准输出 * * note: ./pipe hello world * 仅能输出hello(argv[1]),word(argv[2])不能输出. */ #include #include #include #include #include #include int main(int argc, char **argv) { int pipefd[2]; pid_t pid; char recv_buf[1024]; int len; if(argc perror("pipe()"); exit(1); } pid = fork(); if(-1 == pid) { perror("fork()"); exit(1); } if(0 == pid) { close(pipefd[1]); while((len = read(pipefd[0],recv_buf,10)) > 0 ) write(1,recv_buf,len); puts("\n"); close(pipefd[0]); exit(0); } else { close(pipefd[0]); write(pipefd[1],argv[1],strlen(argv[1])); close(pipefd[1]); wait(NULL); exit(0); } exit(0); } 匿名管道实例2: /* * 父进程通过命令行的方式输入文件路径名(argv[1])写入管道 * 子进程从管道中读取数据并输出到标准输出 * * eg. ./pipe pipe.c * ./pipe ./pipe.c * ./pipe ./home/user/IPC/pipe.c */ #include #include #include #include #include #include int main(int argc, char **argv) { int pipefd[2]; pid_t pid; char recv_buf[1024]; char send_buf[1024]; int recv_len; size_t send_len; FILE *fp = NULL; if(argc < 2) { perror("Usage error:"); exit(1); } if(pipe(pipefd) < 0) { perror("pipe()"); exit(1); } pid = fork(); if(-1 == pid) { perror("fork()"); exit(1); } if(0 == pid) { close(pipefd[1]); while((recv_len = read(pipefd[0],recv_buf,10)) > 0 ) write(1,recv_buf,recv_len); puts("\n"); close(pipefd[0]); exit(0); } else { close(pipefd[0]); fp = fopen(argv[1],"r"); if(NULL == fp) { perror("fopen()"); exit(1); } while((send_len = fread(send_buf,1,10,fp)) > 0) write(pipefd[1],send_buf,send_len); fclose(fp); close(pipefd[1]); wait(NULL); exit(0); } exit(0); } 命名管道实例:公共头文件public.h: #ifndef PUBLIC_H__ #define PUBLIC_H__ #define MKFIFO_NAME "tp" //定义管道文件名 #endif写端代码(write.c): #include #include #include #include #include #include #include #include #include #include "public.h" #define ERR_EXIT(m) \ do { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) int main(int argc, char *argv[]) { mkfifo(MKFIFO_NAME, 0644); int infd = open("Makefile", O_RDONLY); if (infd == -1) ERR_EXIT("open error"); int outfd; outfd = open(MKFIFO_NAME, O_WRONLY); if (outfd == -1) ERR_EXIT("open error"); char buf[1024]; int n; while ((n = read(infd, buf, 1024)) > 0) write(outfd, buf, n); close(infd); close(outfd); return 0; }读端代码(read.c): #include #include #include #include #include #include #include #include #include #include "public.h" #define ERR_EXIT(m) \ do { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) int main(int argc, char *argv[]) { int outfd = open("Makefile2", O_WRONLY | O_CREAT | O_TRUNC, 0644); if (outfd == -1) ERR_EXIT("open error"); int infd; infd = open(MKFIFO_NAME, O_RDONLY); if (infd == -1) ERR_EXIT("open error"); char buf[1024]; int n; while ((n = read(infd, buf, 1024)) > 0) write(outfd, buf, n); close(infd); close(outfd); unlink(MKFIFO_NAME); // delete a name and possibly the file it refers to return 0; }PS:部分内容来源于其他博客,侵权删。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |