匿名管道(pipe)和命名管道(mkfifo)

您所在的位置:网站首页 网名与命名缘由的区别 匿名管道(pipe)和命名管道(mkfifo)

匿名管道(pipe)和命名管道(mkfifo)

2024-02-26 21:54| 来源: 网络整理| 查看: 265

匿名管道(pipe)和命名管道(mkfifo)

进程间通信必须通过内核提供的通道。

1、匿名管道

匿名管道通过打开的文件描述符来标识的。——用于具有亲缘关系间进程之间的通信。

img

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

需要注意的是打开的文件描述符默认是阻塞的.

管道的创建

img

管道文件大小为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