Linux 进程3-fork创建子进程继承父进程缓冲区验证
目录
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:父进程执行,数据存在缓冲区
运行结果:

相关文章:
Linux 进程3-fork创建子进程继承父进程缓冲区验证
目录 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…...
应用服务接口第二次请求一直pending问题
目录 一、问题背景二、问题排查过程三、解决方案四、总结 一、问题背景 升级内容发布到灰度环境,验证相关服务,查看接口调用日志,发现第一次请求正常,第二次相同接口请求就一直pending,其他服务也是如此 二、问题排查…...
基于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 擅长理解复杂的文档元素,包括交错图像、数学表达式、表格和高级布局(如 LaTeX 格式)。该模型可以更深入地理解丰富的文档,尤其是包含图表、图形、公式和数字的科学论文…...
计算机二级(C语言)考试高频考点总汇(三)—— 结构体和共用体、结构体对齐规则、联合体大小计算
目录 九、结构体和共用体 十、结构体对齐规则 十一、联合体大小计算 九、结构体和共用体 141. 结构体是(不同类型成员的集合),是⼀种用户自定义的数据类型,可以将不同类型的成员组合在⼀起,用于表示(复…...
transformers中学习率warmup策略具体如何设置
在使用 get_linear_schedule_with_warmup(如 Hugging Face Transformers 库中的学习率调度器)时,参数的合理设置需要结合 数据量(dataset size)、批次大小(batch size) 和 训练轮数(…...
“线程通信“一个案例
今天在处理项目需求的时候, 遇到这样一个问题: 项目中需要将用户界面上传的某种模型文件转换成另一种格式的文件, 以便进行预览操作. 而这个转换的过程需要调用到专业软件的脚本程序, 简单来说就是一个比较耗时的步骤. 并且这个转换还要分为两步进行, 需要调用两个脚本程序. 简…...
Charles抓HTTPS包
一、电脑端 1、证书下载与安装 安装完之后,重新点开看一看,确认下证书状态,安装的没问题 2、charles设置 抓电脑端要把这个点开 3、抓包 正经人看浏览器的包一般是F12,不过这里就用浏览器代替电脑软件了 如果配制好charles之后…...
JavaScript模板字符串:
1.示例代码(包含注释): <!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.集成开发工具很多,其中目前使用比较多的是: IntelliJ IDEA(这个居多,IDEA在提示功能方面要强于Eclipse,也就是说IDEA使用起来比Eclipse更加智能,更好用。JetBrai…...
将网络安全和第三方风险管理与业务目标相结合
在网络安全风险领域,我们经常遇到与企业语言不通的问题。这可能导致网络安全风险管理计划得不到支持。当发现网络安全风险时,困难在于以符合组织语言和目标的方式来表达它。 第三方风险属于另一个灰色地带。在组织内部,许多利益相关者&#…...
NO.58十六届蓝桥杯备战|基础算法-枚举|普通枚举|二进制枚举|铺地毯|回文日期|扫雷|子集|费解的开关|Even Parity(C++)
枚举 顾名思义,就是把所有情况全都罗列出来,然后找出符合题⽬要求的那⼀个。因此,枚举是⼀种纯暴⼒的算法。 ⼀般情况下,枚举策略都是会超时的。此时要先根据题⽬的数据范围来判断暴⼒枚举是否可以通过。 使⽤枚举策略时…...
postman测试调用WebService时不会自动添加命名空间
这两天在学习调用webservice,发现Postman直接调用时,返回 no namesapce on "myservice" element. you must send a soap message 找了很久,才明白,Postman 不会自动为请求添加命名空间,得手动在请求的 XML 数…...
【已解决】Git:为什么 .gitignore 不生效?如何停止跟踪已提交文件并阻止推送?
你可能遇到的问题 你已经提交了某个文件夹(如 dataset)到 Git 仓库,之后修改了它,但发现修改内容被 Git 持续跟踪,无法通过 .gitignore 忽略。尝试在 .gitignore 中添加规则后,修改的文件仍然显示为"…...
WebRTC协议全面教程:原理、应用与优化指南
一、WebRTC协议概述 **WebRTC(Web Real-Time Communication)**是一种开源的实时通信协议,支持浏览器和移动应用直接进行音频、视频及数据传输,无需插件或第三方软件。其核心特性包括: P2P传输:点对点直连…...
深度学习框架对比评测:TensorFlow、PyTorch、PaddlePaddle与MXNet的技术演进与应用实践
本文针对当前主流的四大深度学习框架(TensorFlow 2.15、PyTorch 2.2、PaddlePaddle 2.5、MXNet 1.9),从架构设计、开发效率、训练性能、部署能力及生态系统等维度展开系统性评测。通过图像分类、自然语言处理、强化学习三类典型任务的基准测试…...
Ethernet(以太网)详解
一、Ethernet的定义与核心特性 以太网(Ethernet)是一种 基于IEEE 802.3标准的局域网(LAN)技术,用于设备间通过有线或光纤介质进行数据通信。其核心特性包括: 标准化:遵循IEEE 802.3系列协议&am…...
Python正则表达式(二)
目录 六、re.findall()函数和分组 1、0/1分组情况 2、多分组情况 七、或“|”的用法 1、作用域 2、用法 八、贪婪模式和懒惰模式 1、量词的贪婪模式 2、量词的懒惰模式 九、匹配对象 1、相关函数 六、re.findall()函数和分组 1、0/1分组情况 在正则表达式中&#x…...
学习《JS数据结构与算法》
博主这些日子去实习所以断更了,现在回归想接着学习一下数据结构与算法,学校也有上这门课,但博主去实习很多课都没上,现在自己看书学习一下,每天记录一下自己学习进度规范一下自己,需要这本书的可以私聊博主…...
图解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. 应用场景…...
哪吒汽车:一边熬夜蹦迪,一边找药投医
两年前,威马CEO沈晖发了个短视频,内容是“活下去,像牲口一样活下去”。 如今最能体会沈晖当时心情的,估计就是方运舟了。 作为哪吒汽车创始人兼董事长,他连续多次被限高,为了让哪吒汽车活下去,…...
Linux一步部署主DNS服务器
#!/bin/bash #部署DHCP服务 #userli 20250319if [ "$USER" ! "root" ]then echo"错误:非root用户,权限不足!"exit 0fi#防火墙与高级权限 systemctl stop firewalld && systemctl disable firewalld…...
使用django的DRF业务逻辑应该放在序列化器类还是模型类
在 Django REST Framework (DRF) 中,序列化器和模型类有明确的职责划分。虽然序列化器在反序列化时负责接收、验证和转换数据,但模型类仍是整个系统的核心,承担更底层的职责。以下是详细解析: 一、序列化器 vs 模型类:…...
图片隐私清理工具
图片隐私清理助手:一键清除图片敏感信息的神器 在数字时代,我们每天都会拍摄和分享大量图片,但你是否注意过这些图片中可能暗藏隐私信息?相机的GPS定位、拍摄参数等EXIF数据,都可能在不经意间泄露你的隐私。今天介绍的…...
【UE5】摄像机晃动
目录 效果 步骤 一、游戏中晃动视角 二、Sequence中晃动视角 效果 步骤 一、游戏中晃动视角 1. 新建一个蓝图,父类选择“CameraShakeBase” 这里命名为“BP_MyCameraShake” 打开“BP_MyCameraShake”,根晃动模式这里设置为“Perlin噪点摄像机晃…...
类和对象—继承(1)
目录 1、继承1.1、继承的概念1.2、继承的语法 2、子类访问父类成员2.1、子类中访问父类的成员变量2.2、子类中访问父类的成员方法2.3、super 关键字 3、子类构造方法 1、继承 在 Java 中,类对现实中的实体进行描述,而类实例化的对象用来表示现实中的实体…...
CCF CSP 第33次(2024.03)(2_相似度计算_C++)(字符串中字母大小写转换+哈希集合)
CCF CSP 第33次(2024.03)(2_相似度计算_C) 题目背景:题目描述:输入格式:输出格式:样例1输入:样例1输出:样例1解释:样例2输入:样例2输出…...
试试智能体工作流,自动化搞定运维故障排查
APO 1.5.0版本全新推出的智能体工作流功能,让运维经验不再零散!只需将日常的运维操作和故障排查经验转化为标准化流程,就能一键复用,效率翻倍,从此告别重复劳动,把时间留给更有价值的创新工作。更贴心的是&…...
Linux应用:线程基础
线程介绍 进程是程序在操作系统里的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的一个执行单元,是 CPU 调度和分派的基本单位。一个进程可以包含多个线程,这些线程共享进程的资源,如内存空间、文…...
