Linux 进程3-fork创建子进程继承父进程缓冲区验证

news2025/3/31 11:02:28

目录

1. fork创建子进程继承父进程缓冲区验证

1.1 write向标准输出(终端屏幕)写入数据验证

1.1.1 write函数写入数据不带行缓冲刷新 \n

1.1.2  write函数写入数据带行缓冲刷新 \n

1.2 fork创建前执行printf函数

1.2.1 fork创建前执行printf函数带\n,刷新缓冲区

1.2.2 fork创建前执行printf函数不带\n,缓冲区有缓冲数据

1.3 fork缓冲输出重定向

1.3.1 fork缓冲输出重定向到文件

1.3.2 fork缓冲输出重定向到文件,验证write无缓冲直接输出


1. fork创建子进程继承父进程缓冲区验证

1.1 write向标准输出(终端屏幕)写入数据验证

write函数为系统调用,无缓冲区,写入数据直接输出到终端

1.1.1 write函数写入数据不带行缓冲刷新 \n

程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
	printf("main 开始\n");

	int length = 0;
	char buf[] = "a write to stdout";
	
	//向标准输出(终端屏幕)写入buf数据
	//write函数为系统调用,无缓冲区,数据直接输出到终端。
	length = write(1, buf, strlen(buf));
	if(length != strlen(buf))
	{
	printf("write error\n");
	}
	
	return 0;
}

运行结果:

1.1.2  write函数写入数据带行缓冲刷新 \n

程序:

仅修改上述程序中的 : char buf[] = "a write to stdout\n";

运行结果:

1.2 fork创建前执行printf函数

1.2.1 fork创建前执行printf函数带\n,刷新缓冲区

printf函数带\n,刷新缓冲区,子进程继承父进程缓冲区里面无内容。

程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
	printf("main 开始\n");
	pid_t pid;
	int length = 0;
	char buf[] = "a write to stdout\n";
	//char buf[] = "a write to stdout";
	
	//向标准输出(终端屏幕)写入buf数据
	//write函数为系统调用,无缓冲区,直接输出到终端。
	length = write(1, buf, strlen(buf));
	if(length != strlen(buf))
	{
	printf("write error\n");
	}
	
	//验证不带 \n,子进程会继承,终端缓冲区内容。
	// printf 有\n 时,行缓冲区会刷新,刷新后缓冲区无内容。
	printf("fork 创建前:\n");
	
	pid=fork();
	if(pid<0)
	{
	perror("fail to fork");
	}
	else if(pid==0)
	{
	printf("在子进程中- \n");
	}
	else
	{
	sleep(1);//让子进程先执行完,在执行父进程
	printf("在父进程中- \n");
	}

	return 0;
}

运行结果:printf函数带\n,执行printf("fork 创建前:\n"); 刷新了缓冲区,子进程继承父进程缓冲区里面无内容。不会打印fork之前的printf内容。

1.2.2 fork创建前执行printf函数不带\n,缓冲区有缓冲数据

printf 无\n 时,行缓冲区不会刷新(除非行缓冲数据存满1024字节),缓冲区有缓冲数据。
下次刷新缓冲区时,缓冲区数据会输出。

程序:

仅修改上述程序的 printf("fork 创建前:"); 去掉printf函数的  \n

运行结果:由于执行 printf("fork 创建前:");,printf函数无 \n,缓冲区不会刷新,打印的内容:fork 创建前:,一直存在缓冲区中,没有输出。在fork 创建子进程时,父进程缓冲区数据被子进程继承,等到缓冲区刷新时,才会将 缓冲数据输出。

打印的数据 (main 开始,已不再缓冲区中 ; a write to stdout 无缓冲,已直接输出)。

fork 创建前:在子进程中-    //子进程程序运行,输出
fork 创建前:在父进程中-   //父进程程序运行,输出

1.3 fork缓冲输出重定向

重定向:将终端输出结果,重新定向到文件,缓冲区变为全缓冲。

fork缓冲输出重定向到文件,原来的行缓冲变为全缓冲,只有缓冲区满、人为调用刷新函数(fflush)、程序运行结束才会刷新。即使 printf函数带\n,也不会刷新缓冲区。

1.3.1 fork缓冲输出重定向到文件

程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
	//printf("main 开始\n");
	pid_t pid;
	int length = 0;
	char buf[] = "a write to stdout\n";
	//char buf[] = "a write to stdout";
	
	//向标准输出(终端屏幕)写入buf数据
	//write函数为系统调用,无缓冲区,直接输出到终端。
	length = write(1, buf, strlen(buf));
	if(length != strlen(buf))
	{
	printf("write error\n");
	}
	
	//验证不带 \n,子进程会继承,终端缓冲区内容。
	// printf 有\n 时,行缓冲区会刷新,刷新后缓冲区无内容。
	// printf 无\n 时,行缓冲区不会刷新(除非行缓冲数据存满1024字节),缓冲区有缓冲数据。
	//下次刷新缓冲区时,缓冲区数据会输出。
	printf("fork 创建前:\n");
	
	pid=fork();
	if(pid<0)
	{
	perror("fail to fork");
	}
	else if(pid==0)
	{
	printf("在子进程中- \n");
	}
	else
	{
	sleep(2);//让子进程先执行完,在执行父进程
	printf("在父进程中- \n");
	}

	return 0;
}

运行结果:

(1)终端运行结果

printf函数带\n,执行printf("fork 创建前:\n"); 刷新了缓冲区,子进程继承父进程缓冲区里面无内容。不会打印fork之前的printf内容。写入的的数据 ( a write to stdout 无缓冲,已直接输出)。

(2)执行./a.out > test.txt ,输出重定向到文件

fork缓冲输出重定向到文件,原来的行缓冲变为全缓冲只有缓冲区满、人为调用刷新函数(fflush)、程序运行结束才会刷新。即使 printf函数带\n,也不会刷新缓冲区。

运行结果:

写入的的数据 ( a write to stdout 无缓冲,直接输出)。

执行printf("fork 创建前:\n"); 原本会刷新了缓冲区,但重定向后,行缓冲变为全缓冲,\n不会刷新缓冲区。子进程继承了父进程缓冲区数据,子进程执行时,也会打印:fork 创建前:\n;

1.3.2 fork缓冲输出重定向到文件,验证write无缓冲直接输出

在main函数开始,加入 printf("main 开始\n");

程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
	printf("main 开始\n");
	pid_t pid;
	int length = 0;
	char buf[] = "a write to stdout\n";
	//char buf[] = "a write to stdout";
	
	//向标准输出(终端屏幕)写入buf数据
	//write函数为系统调用,无缓冲区,直接输出到终端。
	length = write(1, buf, strlen(buf));
	if(length != strlen(buf))
	{
	printf("write error\n");
	}
	
	//验证不带 \n,子进程会继承,终端缓冲区内容。
	// printf 有\n 时,行缓冲区会刷新,刷新后缓冲区无内容。
	// printf 无\n 时,行缓冲区不会刷新(除非行缓冲数据存满1024字节),缓冲区有缓冲数据。
	//下次刷新缓冲区时,缓冲区数据会输出。
	printf("fork 创建前:\n");
	
	pid=fork();
	if(pid<0)
	{
	perror("fail to fork");
	}
	else if(pid==0)
	{
	printf("在子进程中- \n");
	}
	else
	{
	sleep(2);//让子进程先执行完,在执行父进程
	printf("在父进程中- \n");
	}

	return 0;
}

运行结果:

(1)终端运行

printf("fork 创建前:\n"); 带有行缓冲刷新 \n ,子进程继承父进程缓冲区时,父进程缓冲区无数据,不会打印fork 创建前:

(2)执行./a.out > test.txt ,输出重定向到文件

函数运行时,从main函数开始:

①首先执行,printf("main 开始\n"); 但是,由于重定向后,行缓冲变为全缓冲,\n不会刷新缓冲区(只有缓冲区满、人为调用刷新函数(fflush)、程序运行结束才会刷新)。

子进程继承了父进程缓冲区数据,printf("main 开始\n");,子进程执行时,等待缓冲区刷新时,才会输出数据。

②执行写入函数 write(1, buf, strlen(buf));,写入数据,由于写入的的数据 ( a write to stdout 无缓冲,将会直接输出到终端)。

③执行printf("fork 创建前:\n"); 原本会刷新了缓冲区,但重定向后,行缓冲变为全缓冲,\n不会刷新缓冲区。

子进程继承了父进程缓冲区数据,printf("fork 创建前:\n"); ,子进程执行时,等待缓冲区刷新时,才会输出数据。

④子进程执行完,父进程执行,打印输出过程与子进程相同。

终端打印数据顺序分析:全缓冲,没有调用刷新函数,函数程序运行结束才会刷新缓冲区。

函数执行过程:

printf("main 开始\n");         //顺序2:子进程执行,数据存在缓冲区
write(1, buf, strlen(buf));         //顺序1:子进程执行时,最先输出到终端,无缓冲
printf("fork 创建前:\n");        //顺序3:子进程执行,数据存在缓冲区
printf("在子进程中- \n");        //顺序4:子进程执行,数据存在缓冲区

printf("main 开始\n");        /顺序5:父进程执行,数据存在缓冲区
printf("fork 创建前:\n");   /顺序6:父进程执行,数据存在缓冲区
printf("在父进程中- \n");     /顺序7:父进程执行,数据存在缓冲区

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2323303.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

应用服务接口第二次请求一直pending问题

目录 一、问题背景二、问题排查过程三、解决方案四、总结 一、问题背景 升级内容发布到灰度环境&#xff0c;验证相关服务&#xff0c;查看接口调用日志&#xff0c;发现第一次请求正常&#xff0c;第二次相同接口请求就一直pending&#xff0c;其他服务也是如此 二、问题排查…

基于FPGA的ESP8266无线数据传输(温湿度DTH11、光照强度BH1750、WIFI模块)连接中国移动onenet云平台,仿真+上板

文章目录 一、创建云平台产品设备二、FPGA仿真WIFI模块通信过程仿真分析2.上板 总结 一、创建云平台产品设备 使用串口助手测试传输过程 相关信息记录 二、FPGA仿真WIFI模块通信过程 仿真分析 //各个状态tx_dataalways (posedge clk or negedge rst_n) beginif(!rst_n) beg…

5款视觉OCR开源模型

一、号称「世界上最好的 OCR 模型」Mistral OCR Mistral OCR 擅长理解复杂的文档元素&#xff0c;包括交错图像、数学表达式、表格和高级布局&#xff08;如 LaTeX 格式&#xff09;。该模型可以更深入地理解丰富的文档&#xff0c;尤其是包含图表、图形、公式和数字的科学论文…

计算机二级(C语言)考试高频考点总汇(三)—— 结构体和共用体、结构体对齐规则、联合体大小计算

目录 九、结构体和共用体 十、结构体对齐规则 十一、联合体大小计算 九、结构体和共用体 141. 结构体是&#xff08;不同类型成员的集合&#xff09;&#xff0c;是⼀种用户自定义的数据类型&#xff0c;可以将不同类型的成员组合在⼀起&#xff0c;用于表示&#xff08;复…

Charles抓HTTPS包

一、电脑端 1、证书下载与安装 安装完之后&#xff0c;重新点开看一看&#xff0c;确认下证书状态&#xff0c;安装的没问题 2、charles设置 抓电脑端要把这个点开 3、抓包 正经人看浏览器的包一般是F12&#xff0c;不过这里就用浏览器代替电脑软件了 如果配制好charles之后…

JavaScript模板字符串:

1.示例代码&#xff08;包含注释&#xff09;: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>JS-数…

【系统架构设计师】数据库系统 ③ ( 数据库设计过程 | 概念结构设计 | ER 图 简介 | 概念设计阶段 工作拆分 )

文章目录 一、数据库设计过程 概述二、ER 图 简介1、ER 图 概念2、ER 图 示例3、ER 图 关系类型① 一对一 ( 1:1 ) 关系② 一对多 ( 1:n ) 关系③ 多对多 ( n:n ) 关系 三、概念设计阶段 工作拆分 一、数据库设计过程 概述 数据库设计过程 : 需求分析阶段 : 明确 用户需求 ; …

Servlet开发与生命周期详解-2

一、在集成开发环境当中开发Servlet程序 1.集成开发工具很多&#xff0c;其中目前使用比较多的是&#xff1a; IntelliJ IDEA&#xff08;这个居多&#xff0c;IDEA在提示功能方面要强于Eclipse&#xff0c;也就是说IDEA使用起来比Eclipse更加智能&#xff0c;更好用。JetBrai…

将网络安全和第三方风险管理与业务目标相结合

在网络安全风险领域&#xff0c;我们经常遇到与企业语言不通的问题。这可能导致网络安全风险管理计划得不到支持。当发现网络安全风险时&#xff0c;困难在于以符合组织语言和目标的方式来表达它。 第三方风险属于另一个灰色地带。在组织内部&#xff0c;许多利益相关者&#…

NO.58十六届蓝桥杯备战|基础算法-枚举|普通枚举|二进制枚举|铺地毯|回文日期|扫雷|子集|费解的开关|Even Parity(C++)

枚举 顾名思义&#xff0c;就是把所有情况全都罗列出来&#xff0c;然后找出符合题⽬要求的那⼀个。因此&#xff0c;枚举是⼀种纯暴⼒的算法。 ⼀般情况下&#xff0c;枚举策略都是会超时的。此时要先根据题⽬的数据范围来判断暴⼒枚举是否可以通过。 使⽤枚举策略时&#xf…

Python正则表达式(二)

目录 六、re.findall()函数和分组 1、0/1分组情况 2、多分组情况 七、或“|”的用法 1、作用域 2、用法 八、贪婪模式和懒惰模式 1、量词的贪婪模式 2、量词的懒惰模式 九、匹配对象 1、相关函数 六、re.findall()函数和分组 1、0/1分组情况 在正则表达式中&#x…

图解AUTOSAR_SWS_FlashDriver

AUTOSAR Flash驱动(FLS)模块详解 AUTOSAR基础软件存储抽象层组件详细解析 目录 1. 概述 1.1. Flash驱动模块简介1.2. 功能和作用2. 架构设计 2.1. 模块架构2.2. API接口设计2.3. 状态机设计2.4. 异步操作时序2.5. 配置结构2.6. 任务处理流程3. 总结 3.1. 设计优势3.2. 应用场景…

哪吒汽车:一边熬夜蹦迪,一边找药投医

两年前&#xff0c;威马CEO沈晖发了个短视频&#xff0c;内容是“活下去&#xff0c;像牲口一样活下去”。 如今最能体会沈晖当时心情的&#xff0c;估计就是方运舟了。 作为哪吒汽车创始人兼董事长&#xff0c;他连续多次被限高&#xff0c;为了让哪吒汽车活下去&#xff0c…

Linux一步部署主DNS服务器

​ #!/bin/bash #部署DHCP服务 #userli 20250319if [ "$USER" ! "root" ]then echo"错误&#xff1a;非root用户&#xff0c;权限不足&#xff01;"exit 0fi#防火墙与高级权限 systemctl stop firewalld && systemctl disable firewalld…

图片隐私清理工具

图片隐私清理助手&#xff1a;一键清除图片敏感信息的神器 在数字时代&#xff0c;我们每天都会拍摄和分享大量图片&#xff0c;但你是否注意过这些图片中可能暗藏隐私信息&#xff1f;相机的GPS定位、拍摄参数等EXIF数据&#xff0c;都可能在不经意间泄露你的隐私。今天介绍的…

【UE5】摄像机晃动

目录 效果 步骤 一、游戏中晃动视角 二、Sequence中晃动视角 效果 步骤 一、游戏中晃动视角 1. 新建一个蓝图&#xff0c;父类选择“CameraShakeBase” 这里命名为“BP_MyCameraShake” 打开“BP_MyCameraShake”&#xff0c;根晃动模式这里设置为“Perlin噪点摄像机晃…

类和对象—继承(1)

目录 1、继承1.1、继承的概念1.2、继承的语法 2、子类访问父类成员2.1、子类中访问父类的成员变量2.2、子类中访问父类的成员方法2.3、super 关键字 3、子类构造方法 1、继承 在 Java 中&#xff0c;类对现实中的实体进行描述&#xff0c;而类实例化的对象用来表示现实中的实体…

试试智能体工作流,自动化搞定运维故障排查

APO 1.5.0版本全新推出的智能体工作流功能&#xff0c;让运维经验不再零散&#xff01;只需将日常的运维操作和故障排查经验转化为标准化流程&#xff0c;就能一键复用&#xff0c;效率翻倍&#xff0c;从此告别重复劳动&#xff0c;把时间留给更有价值的创新工作。更贴心的是&…

Linux应用:线程基础

线程介绍 进程是程序在操作系统里的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的一个执行单元&#xff0c;是 CPU 调度和分派的基本单位。一个进程可以包含多个线程&#xff0c;这些线程共享进程的资源&#xff0c;如内存空间、文…

要创建一个基于Spring Boot、Thymeleaf、MyBatis Plus和MySQL的简单表格增删改查(CRUD)项目

文章目录 要创建一个基于Spring Boot、Thymeleaf、MyBatis Plus和MySQL的简单表格增删改查&#xff08;CRUD&#xff09;项目1. 创建Spring Boot项目2.项目配置2.1 依赖yml配置数据库表配置 3.代码实现3.1 实体类3.2 数据访问层3.3 服务层3.4 控制层3.5 Thymeleaf模板 要创建一…