目录
概念:管道是计算机通信领域设计者,设计出的一种单向通信的方式,linux原生提供管道通信
管道都是单向传输内容的
管道中传输的都是"资源"
管道通信不会将内容刷新到磁盘,是内存级的通信(效率高)
管道是半双工的:
全双工:既可以收又可以发,同时进行
半双工:要么在收要么发
- //头文件
- #include
-
- //函数
- int pipe(int pipefd[2]);
-
- //返回值
- //成功返回0,失败返回-1,会设置错误码到errno中
-
- //参数
- //int pipefd[2]
- //输出型参数,我们提供一个数组传入,这个数组会被填充两个文件描述符,pipefd[0]是读,pipefd[1]是写
1、分别以读写方式打开同一个文件
2、fork()创建子进程
3、双方进程各自关闭自己不需要的文件描述符
4、进行通信
5、通信结束
- #include
- #include
- #include
- #include
- #include
- #include
- using namespace std;
-
- int main()
- {
- int pipefd[2]; //创建一个数组,接受文件描述符
- if(pipe(pipefd) < 0) //判断管道是否创建成功
- {
- perror("pipe"); //失败打印pipe,然后退出
- return -1;
- }
-
- pid_t id = fork(); //创建一个进程
- if(id < 0) //判读进程是否创建成功
- {
- perror("fork"); //失败打印fork,然后退出
- return -1;
- }
-
- if(id == 0) //我们让子进程进行读取
- {
- close(pipefd[1]); //关闭写进程
- char buff[64];
- while(1) //进行通信
- {
- ssize_t s = read(pipefd[0], buff, sizeof(buff));
- if(s > 0)
- {
- if(strcmp(buff, "q") == 0)
- {
- cout << "quit" << endl;
- break;
- }
- cout << "parent say: " << buff << endl;
- }
- else if(s == 0)
- {
- cout << "eof" << endl;
- break;
- }
- else
- {
- cout << "read error" << endl;
- break;
- }
- }
- close(pipefd[0]); //关闭读进程
- }
- //父进程进程通信
- close(pipefd[0]); //关闭读
- if(id > 0)
- {
- char buff[64];
- while(1)
- {
- cin >> buff;
- write(pipefd[1], buff, sizeof(buff));
- if(strcmp(buff, "q") == 0)
- {
- break;
- }
- }
- }
-
- //通信结束
- wait(NULL);
- close(pipefd[1]); //关闭写
- return 0;
- }

匿名管道的特点:
管道是用来进行具有血缘关系的进程进行进程间同通信 -- 常用于父子通信
a、写快,读慢,写满就不能写了
b、写慢,读快,管道没有数据的时候,读必须等待
c、写关,读0,表示读到了文件结尾
d、读关,写继续写,os终止写进程
为了解决匿名管道只能父子间通信,产生了命名管道
方式一:
mkfifo指令:
mkfifo 管道名 --创建一个命名管道
方式二:
mkfifo函数
- //头文件
- #include
- #include
- //函数
- int mkfifo(const char *pathname, mode_t mode);
- //返回值 创建成功返回0,失败返回-1
-
- //参数
- //const char *pathname,创建的路径
- //mode_t mode,创建权限
命名管道fifo是p标识管道文件
![]()
1、分别写一个客户端,一个服务端
2、服务端创建命名管道
3、服务端发送信息,客服端接受信息
4、通信结束,客服端和服务端退出
服务端,server.cpp
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- using namespace std;
-
- int main()
- {
- umask(0000); //将权限掩码设置为0000
- if(mkfifo("./fifo", 0666)) //创建命名管道fifo
- {
- perror("mkfifo");
- return -1;
- }
-
- int fd = open("./fifo", O_WRONLY); //以写方式打开命名管道
- if(fd < 0)
- {
- perror("open");
- return -1;
- }
-
- char buff[64];
- while(1)
- {
- cin >> buff;
- write(fd, buff, sizeof(buff));
- if(strcmp(buff, "q") == 0)
- {
- cout << "quit" << endl;
- break;
- }
- }
- unlink("./fifo"); //删除命名管道
- return 0;
- }
客服端,client.cpp
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- using namespace std;
-
- int main()
- {
- umask(0000); //将权限掩码设置为0000
- if(mkfifo("./fifo", 0666)) //创建命名管道fifo
- {
- perror("mkfifo");
- return -1;
- }
-
- int fd = open("./fifo", O_WRONLY); //以写方式打开命名管道
- if(fd < 0)
- {
- perror("open");
- return -1;
- }
-
- char buff[64];
- while(1)
- {
- cin >> buff;
- write(fd, buff, sizeof(buff));
- if(strcmp(buff, "q") == 0)
- {
- cout << "quit" << endl;
- break;
- }
- }
- unlink("./fifo"); //删除命名管道
- return 0;
- }

1、匿名管道是用来进行具有血缘关系的进程进行进程间同通信 -- 常用于父子通信
2、管道具有通过让进程间协同,提供了访问控制 假如写满,需要等待被读取才能继续写入
3、管道提供的是面向流式的服务 -- 面向字节流 -- 协议
4、管道是基于文件的,文件的生命周期是随进程的,管道的生命周期是随子进程的
5、管道是单向通信的(半双工通信的一种特殊情况)
全双工:既可以收又可以发,同时进行
半双工:要么在收要么发