知识概述

  通过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管道的读写端关闭问题相关推荐

  1. Linux学习笔记-管道的读写特性

    目录 理论 栗子 理论 管道的读写特性 1.通过打开两个管道来创建一个双向的管道: 2.管道默认是阻塞性的,当进程从管道中读取数据,若没有数据进程会阻塞: 3.当一个进程往管道中不断地写入数据但是没有 ...

  2. Linux——(管道练习)C实现父子进程通信、兄弟进程通信、多个读写端操作管道及管道缓冲区大小、fifo实现非血缘间进程通信

    一. 父子进程通信 lswc-l 父进程ls写到管道,子进程wc管道的内容 父进程创建管道(拥有读写两端),父进程fork子进程,父进程要将原本输出到屏幕上的内容输出到管道中,用dup实现,然后exe ...

  3. Linux中的pipe(管道)与named pipe(FIFO 命名管道)

    catalogue 1. pipe匿名管道 2. named pipe(FIFO)有名管道 1. pipe匿名管道 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入 ...

  4. 【Linux进程间通信】二、pipe管道

    pipe管道 1. 什么是管道 2. pipe()函数创建管道 2.1 函数原型 2.2 工作原理 2.3 通过实战分析管道的特性 3. 管道的读写行为 4. 管道(缓冲区)大小 5. 管道的优缺点 ...

  5. pipe管道实现进程间的通信

    pipe 1.管道由pipe函数创建 2.管道的本质是伪文件(不占用磁盘空间,只占用内存) 3.管道由两个文件描述符的引用,一个fd[0]读,一个fd[1]写 4.数据从管道的写端流入,读端流出 5. ...

  6. Pipe(管道)的一些理解

    Pipe(管道)的一些理解 管道的概念 管道是操作系统中常见的一种进程间通信方式,它使用于所有POSIX系统以及Windows系列产品. 管道也是unix ipc的最老形式,管道有两种限制: 数据自己 ...

  7. Linux进程通信(一)——pipe管道

    本章内容 采用pipe管道如何进行进程之间的通信 pipe管道进程通信的规则和限制 Linux中pipe管道的实现机制和管理pipe管道的结构体 什么是进程通信 进程通信就是两个进程之间进行数据交换, ...

  8. linux无名管道实验代码,Linux 进程间通讯之创建无名管道和读写无名管道

    Linux进程间通讯的方式: 1. 管道(pipe)和有名管道(FIFO). 2. 信号(signal) 3. 消息队列 4. 共享内存 5. 信号量 6. 套接字(socket) 管道通讯: 无名管 ...

  9. Linux学习之系统编程篇:管道设置为非阻塞及管道的读写行为

    一.管道设置为非阻塞 管道默认读写两端都是堵塞属性,那么怎能才能设置成非阻塞呢? (1)设置读端非阻塞 获得原来的属性 flag: int flags = fcntl(fd[0], F_GETFL); ...

  10. 嵌入式linux的学习笔记-pipe管道(二)

    今天学习了一下pipe管道,用于父子或者相关联的两个进程之间的通讯,pipe使用 pipe()函数建立,必须用于fork建立的进程中,并且需要在fork之前调用,否则是没有效果的,下面是一个例子和用法 ...

最新文章

  1. 函数 —— strncpy() (内存重叠) memcpy() memmove() 一个字符串拷贝给另一个字符串
  2. 卸载受密码保护SEP Norton 11
  3. ASP.NET 4 和 Visual Studio 2010 Web 开发概述
  4. V星入侵(V 2009)第一季全集下载
  5. 自助银行服务系统项目开发_自助服务时代即将结束
  6. BERT4GCN:利用BERT中间层特征增强GCN进行基于方面的情感分类
  7. python -----class(类)中的object是什么意思?
  8. CRM客户关系管理系统HR人事OA系统APP源码
  9. Tomcat 7 部署和配置
  10. PEPS 无钥匙进入系统低频芯片 PCF7991 介绍
  11. 手机扫描识别Vin码识别
  12. My Fifty-eighth - Page - 全排列 - By Nicolas
  13. 深度学习服务器?深度了解一下!
  14. 【2022牛客多校5 A题 Don‘t Starve】DP
  15. 基于redis幂等机制,保证优惠券不会重复发放-13
  16. eclipse:解决 The word is not correctly spelled问题
  17. 安装python环境以及安装pycharm编译器教程
  18. 济南大雨,银座亲历(转载)
  19. 基于机器视觉的机器人智能制造实践应用研究
  20. 屏幕尺寸、分辨率、视口笔记

热门文章

  1. 混合选择集的坐标提起lisp_晓东CAD家园-论坛-A/VLISP-[LISP程序]:请教如何对选择集进行排序-我有(setq ss(ssget _w p0 p1 (list (0 . CIRC...
  2. 【UVA213】Message Decoding(读入技巧+二进制十进制转换)
  3. python火车票查询系统_Python脚本实现12306火车票查询系统
  4. 电脑取消撤销快捷键是什么_必须掌握的十个电脑使用技巧
  5. DeepRacer 找到的最好的奖励函数 reward function
  6. 清华源加速 添加在pip install xxx后面即可
  7. 182.查找重复的电子邮箱
  8. ubuntu python subprocess模块执行python脚本
  9. python中List和Tuple的区别
  10. MATLAB通信仿真实例1:无噪声信道下DSB-SC调制解调器