关于pipe管道的读写端关闭问题
知识概述
通过pipe在内核中创建一个文件,然后可以实现两个进程通信
管道是一种最基本的IPC机制,由 pipe 函数创建:
1 #include <unistd.h> 2 int pipe(int filedes[2]);
调用 pipe 函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过 filedes 参数传出给用户程序两个文件描述符,
filedes[0] 指向管道的读端, filedes[1] 指向管道的写端(很好记,就像0是标准输入1是标准输出一样)。所以管道在用户程序看起来就像一个打开的文件,
通过 read(filedes[0]); 或者 write(filedes[1]); 向这个文件读写数据其实是在读写内核缓冲区。 pipe 函数调用成功返回0,调用失败返回-1。
开辟了管道之后如何实现两个进程间的通信呢?比如可以按下面的步骤通信。
1. 父进程调用 pipe 开辟管道,得到两个文件描述符指向管道的两端。
2. 父进程调用 fork 创建子进程,那么子进程也有两个文件描述符指向同一管道。
3. 父进程关闭管道读端,子进程关闭管道写端。父进程可以往管道里写,子进程可以从管道里读,
管道是用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通信。
#include <stdlib.h> #include <unistd.h> #define MAXLINE 80 int main(void) {int n;int fd[2];pid_t pid;char line[MAXLINE];if (pipe(fd) < 0) {perror("pipe");exit(1);}if ((pid = fork()) < 0) {perror("fork");exit(1);}if (pid > 0) { /* parent */close(fd[0]);write(fd[1], "hello world\n", 12);wait(NULL);} else { /* child */close(fd[1]);n = read(fd[0], line, MAXLINE);write(STDOUT_FILENO, line, n);}return 0; }
问题
父进程只用到写端,因而把读端关闭,子进程只用到读端,因而把写端关闭,然后互相通信,不使用的读端或写端必须关闭,请读者想一想如果不关闭会有什么问题。
思考
1. 如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数等于0),
而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,
再次 read 会返回0,就像读到文件末尾一样。
2. 如果有指向管道写端的文件描述符没关闭(管道写端的引用计数大于0),
而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,
那么管道中剩余的数据都被读取后,再次 read 会阻塞,
直到管道中有数据可读了才读取数据并返回。
考虑到如下代码
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> int main(void) {int n;char buff[128];pid_t pid;int fd[2];if(pipe(fd)<0) {perror("pipe");exit(0);}if((pid=fork())<0){perror("fork");exit(0);}if(pid>0){/* parent */ printf("+++++++++++++\n");close(fd[0]); write(fd[1],"hello world",11);//sleep(5);//write(fd[1],"I am a Student",14);printf("+++++++++++++\n");}else{printf("--------------\n");//close(fd[1]);memset(buff,0,128);n = read(fd[0],buff,20);printf("buff=%s\n",buff);memset(buff,0,128);printf("read twice\n");n = read(fd[0],buff,20);printf("buff=%s\n",buff);printf("--------------\n");}return 0; }
父进程关闭了读端口,通过写端口向pipe中写入了hello world。然后父进程结束。关闭相关文件(读写)描述符
子进程在关闭写端口的时候,父进程结束时候,写文件描述符引用计数为0。所以子进程再次读取后返回0。子进程结束退出。
子进程在不关闭写端口的时候,父进程结束时候,写文件描述符引用计数为1(自己的没关闭)。所以子进程再次读取时候陷入阻塞状态。
因为父进程是在SHELL下执行的。所以当父进程结束时候,Shell进程认为命令执行结束了,于是打印Shell提示符,而子进程等待读取输入。
父进程已经结束,不会给他输入数据,而子进程本身只是为了读取而不是向管道写数据。所以子进程一直在后台运行,通过ps命令可以查看到子进程信息。
所以,子进程只用到读端,因而把写端关闭。防止造成子进程做无用功。。。
转载于:https://www.cnblogs.com/whiteHome/p/4863516.html
关于pipe管道的读写端关闭问题相关推荐
- Linux学习笔记-管道的读写特性
目录 理论 栗子 理论 管道的读写特性 1.通过打开两个管道来创建一个双向的管道: 2.管道默认是阻塞性的,当进程从管道中读取数据,若没有数据进程会阻塞: 3.当一个进程往管道中不断地写入数据但是没有 ...
- Linux——(管道练习)C实现父子进程通信、兄弟进程通信、多个读写端操作管道及管道缓冲区大小、fifo实现非血缘间进程通信
一. 父子进程通信 lswc-l 父进程ls写到管道,子进程wc管道的内容 父进程创建管道(拥有读写两端),父进程fork子进程,父进程要将原本输出到屏幕上的内容输出到管道中,用dup实现,然后exe ...
- Linux中的pipe(管道)与named pipe(FIFO 命名管道)
catalogue 1. pipe匿名管道 2. named pipe(FIFO)有名管道 1. pipe匿名管道 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入 ...
- 【Linux进程间通信】二、pipe管道
pipe管道 1. 什么是管道 2. pipe()函数创建管道 2.1 函数原型 2.2 工作原理 2.3 通过实战分析管道的特性 3. 管道的读写行为 4. 管道(缓冲区)大小 5. 管道的优缺点 ...
- pipe管道实现进程间的通信
pipe 1.管道由pipe函数创建 2.管道的本质是伪文件(不占用磁盘空间,只占用内存) 3.管道由两个文件描述符的引用,一个fd[0]读,一个fd[1]写 4.数据从管道的写端流入,读端流出 5. ...
- Pipe(管道)的一些理解
Pipe(管道)的一些理解 管道的概念 管道是操作系统中常见的一种进程间通信方式,它使用于所有POSIX系统以及Windows系列产品. 管道也是unix ipc的最老形式,管道有两种限制: 数据自己 ...
- Linux进程通信(一)——pipe管道
本章内容 采用pipe管道如何进行进程之间的通信 pipe管道进程通信的规则和限制 Linux中pipe管道的实现机制和管理pipe管道的结构体 什么是进程通信 进程通信就是两个进程之间进行数据交换, ...
- linux无名管道实验代码,Linux 进程间通讯之创建无名管道和读写无名管道
Linux进程间通讯的方式: 1. 管道(pipe)和有名管道(FIFO). 2. 信号(signal) 3. 消息队列 4. 共享内存 5. 信号量 6. 套接字(socket) 管道通讯: 无名管 ...
- Linux学习之系统编程篇:管道设置为非阻塞及管道的读写行为
一.管道设置为非阻塞 管道默认读写两端都是堵塞属性,那么怎能才能设置成非阻塞呢? (1)设置读端非阻塞 获得原来的属性 flag: int flags = fcntl(fd[0], F_GETFL); ...
- 嵌入式linux的学习笔记-pipe管道(二)
今天学习了一下pipe管道,用于父子或者相关联的两个进程之间的通讯,pipe使用 pipe()函数建立,必须用于fork建立的进程中,并且需要在fork之前调用,否则是没有效果的,下面是一个例子和用法 ...
最新文章
- 函数 —— strncpy() (内存重叠) memcpy() memmove() 一个字符串拷贝给另一个字符串
- 卸载受密码保护SEP Norton 11
- ASP.NET 4 和 Visual Studio 2010 Web 开发概述
- V星入侵(V 2009)第一季全集下载
- 自助银行服务系统项目开发_自助服务时代即将结束
- BERT4GCN:利用BERT中间层特征增强GCN进行基于方面的情感分类
- python -----class(类)中的object是什么意思?
- CRM客户关系管理系统HR人事OA系统APP源码
- Tomcat 7 部署和配置
- PEPS 无钥匙进入系统低频芯片 PCF7991 介绍
- 手机扫描识别Vin码识别
- My Fifty-eighth - Page - 全排列 - By Nicolas
- 深度学习服务器?深度了解一下!
- 【2022牛客多校5 A题 Don‘t Starve】DP
- 基于redis幂等机制,保证优惠券不会重复发放-13
- eclipse:解决 The word is not correctly spelled问题
- 安装python环境以及安装pycharm编译器教程
- 济南大雨,银座亲历(转载)
- 基于机器视觉的机器人智能制造实践应用研究
- 屏幕尺寸、分辨率、视口笔记
热门文章
- 混合选择集的坐标提起lisp_晓东CAD家园-论坛-A/VLISP-[LISP程序]:请教如何对选择集进行排序-我有(setq ss(ssget _w p0 p1 (list (0 . CIRC...
- 【UVA213】Message Decoding(读入技巧+二进制十进制转换)
- python火车票查询系统_Python脚本实现12306火车票查询系统
- 电脑取消撤销快捷键是什么_必须掌握的十个电脑使用技巧
- DeepRacer 找到的最好的奖励函数 reward function
- 清华源加速 添加在pip install xxx后面即可
- 182.查找重复的电子邮箱
- ubuntu python subprocess模块执行python脚本
- python中List和Tuple的区别
- MATLAB通信仿真实例1:无噪声信道下DSB-SC调制解调器