pipe和fork浅析

2023-11-06

pipe和fork浅析

fork

fork()是linux上创建子进程的系统调用,fork()函数一次调用两次返回,在父进程返回值是子进程的进程id,在子进程的返回值是0,fork()创建出来的子进程会从fork()函数后面开始执行执行

#include <unistd.h>  
#include <iostream>
int main ()   
{   
    pid_t fpid; //fpid表示fork函数返回的值  
    fpid=fork();   
    if (fpid == 0) 
	{  

        std::cout << "\n我是子进程:" << getpid() << std::endl;
    }  
    else 
	{  
        std::cout << "我是父进程,子进程的id:" << fpid;
    }  
    return 0;  
} 

在这里插入图片描述

pipe

pipe管道是父子进程用来通信的一种方式,管道的特质:

  1. 其本质是一个伪文件(实为内核缓冲区)

  2. 由两个文件描述符引用,一个表示读端,一个表示写端。

  3. 规定数据从管道的写端流入管道,从读端流出。

管道的局限性:
① 数据自己读不能自己写。

② 数据一旦被读走,便不在管道中存在,不可反复读取。

③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。

④ 只能在有公共祖先的进程间使用管道。

pipe函数是用来创建管道的,函数原型:
int pipe(int pipefd[2]); 成功:0;失败:-1,设置errno
函数调用成功返回r/w两个文件描述符。无需open,但需手动close。规定:fd[0] → r,fd[1] → w。

那如何实现父子进程的通信呢?一般分为三个步骤如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 父进程调用pipe函数创建管道,得到两个文件描述符fd[0]、fd[1]指向管道的读端和写端。

  2. 父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。

  3. 父进程关闭管道读端,子进程关闭管道写端。父进程可以向管道中写入数据,子进程将管道中的数据读出。由于管道是利用环形队列实现的,数据从写端流入管道,从读端流出,这样就实现了进程间通信。

下面看一段代码:


#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string>
#include <iostream>
 
 
void sys_err(const char *str)
 
{
	perror(str);
	exit(1);
}
 
 
int main(void)
 
{
	pid_t pid;
	char buf[1024];
	int fd[2];
	std::string str = "test for pipe\n";
	if (pipe(fd) == -1)
	{	
		sys_err("pipe");
	}
	pid = fork();
	if (pid < 0)
	{
		sys_err("fork err");
	} 
	else if (pid == 0) 
	{
		close(fd[1]);
		read(fd[0], buf, sizeof(buf));
		std::cout << buf;
		close(fd[0]);
	} 
	else 
	{
		close(fd[0]);
		write(fd[1], str.c_str(), str.size());
		wait(NULL);
		std::cout << "子进程结束" << std::endl;
		close(fd[1]);
	}
	return 0;
}

思考:为甚么,程序中没有使用sleep函数,但依然能保证子进程运行时一定会读到数据呢?

管道的读写行为:
管道的读写行为
使用管道需要注意以下4种特殊情况(假设都是阻塞I/O操作,没有设置O_NONBLOCK标志):

  1. 如果所有指向管道写端的文件描述符都关闭了(管道写端引用计数为0),而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。

  2. 如果有指向管道写端的文件描述符没关闭(管道写端引用计数大于0),而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。

  3. 如果所有指向管道读端的文件描述符都关闭了(管道读端引用计数为0),这时有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。当然也可以对SIGPIPE信号实施捕捉,不终止进程。具体方法信号章节详细介绍。

  4. 如果有指向管道读端的文件描述符没关闭(管道读端引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写入数据并返回。

所以下面如果CPU切换到子进程执行到read的时候发现管道里面没有数据就会阻塞,等到CPU切换到父进程,然后向管道里面写数据后,CPU切换回子进程read就返回了。

参考博客:
https://www.cnblogs.com/dongguolei/p/8086346.html
https://blog.csdn.net/qq_42914528/article/details/82023408

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pipe和fork浅析 的相关文章

  • 使用无效命令进行 fork 会导致 valgrind 中的内存泄漏

    我有以下代码 它在分叉内执行无效命令 以下代码在 valgrind 中返回内存泄漏 include
  • 模拟用户输入以使用不同参数多次调用脚本

    我必须使用提供的脚本 该脚本在脚本运行时接受用户输入而不是参数 我无法解决这个问题 脚本的一个例子是 bin bash echo param one read one doSomething echo param two read two
  • 使用 WGET 运行 cronjob PHP

    我尝试执行一个 cron 并每 5 分钟运行一个 url 我尝试使用 WGET 但我不想下载服务器上的文件 我只想运行它 这是我使用的 crontab 5 wget http www example com cronit php 除了 wg
  • 尝试 SSH 时设备的 ioctl 不合适

    我正在尝试通过 SSH 连接几台服务器并尝试获取sudo l每个服务器的输出 下面是我正在执行的脚本 bin bash serverlist tmp servers while IFS read r server netgroup user
  • 不同GIT版本的GIT合并结果不同

    在不同的 GIT 版本上运行 merge 命令我们得到不同的结果 命令是 git merge no ff origin master codeline Results 版本2 1 4 gt 合并成功 版本1 7 1 gt 同一提交上的同一合
  • :: 右侧的非法标记

    我有以下模板声明 template
  • 命令行参数中的“-”(破折号)有什么魔力?

    例子 创建 ISO 映像并将其直接刻录到 CD mkisofs V Photos r home vivek photos cdrecord v dev dev dvdrw 更改到上一个目录 cd 侦听端口 12345 并解压发送到该端口的数
  • 让“git pull”在拉取不同分支时要求确认

    当同时处理许多项目和分支时 我偶尔会犯一些愚蠢的错误 比如拉入错误的分支 例如在分支上master I did git pull origin dangerous code并且有一段时间没有注意到这一点 这个小错误造成了很大的混乱 当我尝试
  • 访问 Linux 线程(pthreads)的本地堆栈

    我目前正在实现一个使用多线程但对总内存消耗有要求的应用程序 我希望有一个主线程执行 I O 并有几个工作线程执行计算 目前 我在主堆栈上有几个可供工作人员访问的数据结构 我使用 OpenMP 进行工作分配 由于主 工作者模式不能很好地与 O
  • 操作系统崩溃的常见原因[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有兴趣了解 操作系统崩溃 不限于Windows崩溃 最常见的技术原因 从操作系统编程的角度 有哪些 我正在寻找一个不像 打开太多应用
  • 是否有我可以运行的操作系统命令来确定是否在基于 Xen 的虚拟机内运行

    我可以在基于 Xen 的虚拟机中运行一个操作系统命令来告诉我它是一个虚拟机而不是物理机 我听说内核对此有一些自我意识智能 例如就像 ps 输出中的额外列之类的 我知道 vmstat 提供了 st 列 但我在运行 Linux 内核 2 6 1
  • Linux下的C#,Process.Start()异常“没有这样的文件或目录”

    我在使用 Process 类调用程序来启动程序时遇到问题 可执行文件的层次结构位于 bin 目录下 而当前工作目录需要位于 lib 目录下 project bin a out this is what I need to call lib
  • 在单个命令中使用前缀重命名文件夹中的所有文件

    重命名带有前缀的文件夹中的所有文件 Unix 假设一个文件夹有两个文件 a txt b pdf 那么它们都应该从一个命令重命名为 Unix a txt Unix b pdf 如果您的文件名包含没有空格并且你没有任何子目录 你可以使用一个简单
  • bash双括号问题

    我对 bash 脚本非常陌生 在使用双括号时遇到了问题 我似乎无法让它们在 Ubuntu Server 11 10 中工作 我的下面的脚本位于 if test sh 中 bin bash if 14 14 then echo FOO fi
  • Bash 中 $() 和 () 之间的区别

    当我打字时ls l echo file 支架的输出 这只是简单的回显 被获取并传递到外部ls l命令 就等于简单的ls l file 当我打字时ls l echo file 我们有错误 因为不能嵌套 内部外部命令 有人可以帮助我理解之间的区
  • jpackage linux 创建的桌面文件不足

    我刚刚开始使用 jpackage 它是一个非常棒的工具 只要迈出一步 我的肩上的工作就减轻了很多 我对看起来硬编码且无法定制的东西越感到惊讶 JPackage 自动生成启动器 lib
  • 使用 MongoDB docker 镜像停止虚拟机而不丢失数据

    我已经在 AWS EC2 上的虚拟机中安装了官方的 MongoDB docker 映像 并且数据库上已经有数据 如果我停止虚拟机 以节省过夜费用 我会丢失数据库中包含的所有数据吗 在这些情况下我怎样才能让它持久 有多种选择可以实现此目的 但
  • 使用netcat将unix套接字传输到tcp套接字

    我正在尝试使用以下命令将 unix 套接字公开为 tcp 套接字 nc lkv 44444 nc Uv var run docker sock 当我尝试访问时localhost 44444 containers json从浏览器中 它不会加
  • ARM 系统调用的接口是什么?它在 Linux 内核中的何处定义?

    我读过有关 Linux 中的系统调用的内容 并且到处都给出了有关 x86 架构的描述 0x80中断和SYSENTER 但我无法追踪 ARM 架构中系统调用的文件和进程 任何人都可以帮忙吗 我知道的几个相关文件是 arch arm kerne
  • Docker DNS 设置

    我尝试使用自定义网络和 dos 设置创建 docker 容器 docker网络创建 driver bridge opt com docker network bridge enable ip masquerade true opt com

随机推荐

  • 解决curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused 问题

    自动化使用要去下载图像识别的工具 Tesseract mac 需要用到brew 但是我的电脑没有 就先需要下载homebrew 然而按照官网的命令 bin bash c curl fsSL https raw githubuserconte
  • 将一个链表分为奇偶两个链表

    1 问题描述 设计一个算法 将一个头结点为A的单链表 其数据域为整数 分解成两个单链表A和B 使得A链表只含有原来链表data域为奇数的节点 而B链表只含有原链表中data域为偶数的节点 而且保持原来的顺序 2 思路分析 这个问题不是在线网
  • python pandas.set_option()详解

    一 简介 set option是pandas里的一个函数 用法为pandas set option pat value 主要作用是设置一些指定参数的值 供设置的选项如下 后面会逐一进行介绍 compute use bottleneck us
  • python研究生导师_研究生导师布置的作业!利用Python和API收集与分析网络数据!...

    猜猜看 下面这一组调查对象是什么 为什么会这样呢 因为我在布置作业的时候 很贴心地给了一个样例 是我之前写的一篇教程 如何用R和API免费获取Web数据 于是 多组作业 都雷同 讲到这里 他们一副不好意思的表情 我却发觉 这里蕴藏着一个问题
  • 上传文件,提交数据---FormData对象格式

    上传文件 提交数据 FormData对象格式 在进行上传文件 例如Excel 时 处理的几步 否则无法上传 一 修改请求头 在修改请求头 是至关重要的 因为请求数据格式是不同的 header multipart form data 注 在写
  • 4- OpenCV+TensorFlow 入门人工智能图像处理-灰度化处理

    图片特效及线段文字的绘制 特效1 灰度处理 mark 完成彩色图片灰度化 彩色图片有三个颜色通道RGB 灰度图片也是三通道的话 RGB值相等 单通道的灰度图片的值 需要经过RGB值进行计算 图中两个公式 一个是取均值 一个是根据公式 特效2
  • OD-求字符串中所有整数的最小和(Python)

    题目描述 说明 字符串s 只包含 a z A Z 合法的整数包括 1 正整数 一个或者多个0 9组成 如 0 2 3 002 102 2 负整数 负号 开头 数字部分由一个或者多个0 9组成 如 0 012 23 00023 输入描述 包含
  • 华为云DevCloud平台部署bootdo博客论坛实战【开发者专属集市】

    华为云DevCloud平台部署bootdo博客论坛实战 开发者专属集市 一 bootdo blog开源博客介绍 二 本次实践所用工具及平台 三 购买华为RDS数据库 1 购买RDS数据库 2 查看RDS数据库状态 四 创建项目 1 登录华为
  • sqli-labs通关记录

    sqli lab通关记录 docker搭建 运行 docker info 查看docker信息 确认docker正常 搜索sqli labs docker search sqli labs 建立镜像 docker pull acgpiano
  • sharding-jdbc 分库分表配置方案

    Java配置 Yaml配置 Spring Boot配置 Spring命名空间配置 http shardingsphere io document current cn manual sharding jdbc configuration c
  • 【送书活动】AI时代,程序员需要焦虑吗?

    前言 作者主页 雪碧有白泡泡 个人网站 雪碧的个人网站 推荐专栏 java一站式服务 React从入门到精通 前端炫酷代码分享 从0到英雄 vue成神之路 uniapp 从构建到提升 从0到英雄 vue成神之路 解决算法 一个专栏就够了 架
  • C++的std::is_same与std::decay

    一 背景 有一个模板函数 函数在处理int型和double型时需要进行特殊的处理 那么怎么在编译期知道传入的参数的数据类型是int型还是double型呢 include
  • 第五课 for循环(1)--循环次数控制

    第五课 for循环 1 循环次数控制 循环引入 例题5 1 画下面形状的5级梯形 分析 研究问题的方法之一是 从简单到复杂 步骤 说明 图形 步骤1 先分析简单的1级梯形基本问题 步骤2 代码为 pen fd 30 pen rt 90 pe
  • 为什么手机短信长度限制70个中文、160个英文???

    手机短信的长度是由编码决定的 根据国际标准 每条短信最多发送1120位 合 1120 8 140 一个字节占8位 140字节的内容 如果发送纯英文字符 由于英文ASCII采用 7位编码 所以1120位的限额可以传送1120 7 160个字符
  • VUE调用高德地图之热力图

    上次用VUE实现了高德地图的轨迹回放 现在来实现热力图功能 照例 第一步 加载JS AP 在public index html中加入 将官方demo转换为vue代码 放置地图 初始化map对象 生成热力图map 完整代码如下
  • latex表格中的字上下垂直居中

    单元格内容纵向靠上对齐 而是表线距单元格内容太近 调整表线和单元格内容之间的距离 可以通过重定义 arraystretch 来解决 renewcommand arrarstretch
  • Cannot apply to AuthenticationConfiguration already built object

    前言 Spring Security 在Spring Boot 2 7 0中升级已弃用的WebSecurityConfigrerAdapter 并且根据 EnableWebSecurity推荐自定义配置类后 还是错误的问题 失败的案例 首先
  • 多元线性回归模型的F检验

    F检验 对于多元线性回归模型 在对每个回归系数进行显著性检验之前 应该对回归模型的整体做显著性检验 这就是 F检验 当检验被解释变量 yt与一组解释变量 x 1 x 2 xk 1是否存在回归关系时 给出的零假设与备择假设分别是 H0 b1
  • vc++2010安装教程

    vc 2010是微软公司开发的一个专门用来编写C语言或C 的一个简化般的IDE 本章我们就来安装一下这个IDE 链接 https pan baidu com s 18TEvNMeUSFtSrysWNZ 4nw提取码 cnmk这个百度网盘里面
  • pipe和fork浅析

    pipe和fork浅析 fork pipe fork fork 是linux上创建子进程的系统调用 fork 函数一次调用两次返回 在父进程返回值是子进程的进程id 在子进程的返回值是0 fork 创建出来的子进程会从fork 函数后面开始