fork与行缓冲

腾讯面试题--程序一共输出多少个“-” 题目详情: 请判断下列程序一共输出多少个“-”; int main(void) { int i; for(i=0; i<2; i++){ fork(); printf("-"); } return 0; } 题目分析: fork()出的子进程会复制父进程的变量值,缓存信息等, 1、当i=0时,父进程A创建出一个子进程A1,A进程的输出缓冲区会增加一个“-”,A1 阅读详情

题目:请问下面的程序一共输出多少个“-”?

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
int main(void) 
{ 
   int i; 
   for(i=0; i<2; i++){ 
      fork(); 
      printf("-"); 
   } 
   return 0; 
}

如果你对fork()的机制比较熟悉的话,这个题并不难,输出应该是6个“-”,但是,实际上这个程序会很tricky地输出8个“-”。

要讲清这个题,我们首先需要知道fork()系统调用的特性,

  • fork()系统调用是Unix下以自身进程创建子进程的系统调用,一次调用,两次返回,如果返回是0,则是子进程,如果返回值>0,则是父进程(返回值是子进程的pid),这是众为周知的。
  • 还有一个很重要的东西是,在fork()的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令,变量值,程序调用栈,环境变量,缓冲区,等等。

所以,上面的那个程序为什么会输入8个“-”,这是因为printf(“-”);语句有buffer,所以,对于上述程序,printf(“-”);把“-”放到了缓存中,并没有真正的输出,在fork的时候,缓存被复制到了子进程空间,所以,就多了两个,就成了8个,而不是6个。

另外,多说一下,我们知道,Unix下的设备有“块设备”和“字符设备”的概念,所谓块设备,就是以一块一块的数据存取的设备,字符设备是一次存取一个字符的设备。磁盘、内存都是块设备,字符设备如键盘和串口。块设备一般都有缓存,而字符设备一般都没有缓存。

对于上面的问题,我们如果修改一下上面的printf的那条语句为:

printf("-\n");

或是

printf("-"); 
fflush(stdout);

就没有问题了(就是6个“-”了),因为程序遇到“\n”,或是EOF,或是缓中区满,或是文件描述符关闭,或是主动flush,或是程序退出,就会把数据刷出缓冲区。需要注意的是,标准输出是行缓冲,所以遇到“\n”的时候会刷出缓冲区,但对于磁盘这个块设备来说,“\n”并不会引起缓冲区刷出的动作,那是全缓冲,你可以使用setvbuf来设置缓冲区大小,或是用fflush刷缓存。

我估计有些朋友可能对于fork()还不是很了解,那么我们把上面的程序改成下面这样:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
int main(void) 
{ 
   int i; 
   for(i=0; i<2; i++){ 
      fork(); 
      //注意:下面的printf有“\n” 
      printf("ppid=%d, pid=%d, i=%d \n", getppid(), getpid(), i); 
   } 
   sleep(10); //让进程停留十秒,这样我们可以用pstree查看一下进程树 
   return 0; 

}

于是,上面这段程序会输出下面的结果,(注:编译出的可执行的程序名为fork)

ppid=8858, pid=8518, i=0 

ppid=8858, pid=8518, i=1 

ppid=8518, pid=8519, i=0 

ppid=8518, pid=8519, i=1 

ppid=8518, pid=8520, i=1 

ppid=8519, pid=8521, i=1 

$ pstree -p | grep fork 

|-bash(8858)-+-fork(8518)-+-fork(8519)---fork(8521) 

|            |            `-fork(8520)

面对这样的图你可能还是看不懂,没事,我好事做到底,画个图给你看看:

注意:上图中的我用了几个色彩,相同颜色的是同一个进程。于是,我们的pstree的图示就可以成为下面这个样子:(下图中的颜色与上图对应)

这样,对于printf(“-”);这个语句,我们就可以很清楚的知道,哪个子进程复制了父进程标准输出缓中区里的的内容,而导致了多次输出了。(如下图所示,就是我阴影并双边框了那两个子进程)

 

http://coolshell.cn/articles/7965.html

Linux C/C++ or 嵌入式面试之《多进程多线程编程系列》(8) fork笔试题 题目:请问下面的程序一共输出多少个“-”? #include <stdio.h> #include <unistd.h> int main(void) { int i; for(i=0; i<2; i++){ fork(); printf("-"); } return 0; } 如果你对fork()的机制比较熟悉的话,这个题并不难,输出应该是6个“-”,但是,实际上这个程序会很tricky地输出8个“-”。 要讲清这个题 阅读详情

相关推荐

[技术解析] SGDC驱动的轻量级IoT入侵检测:特征选择与模型优化的实战指南

本文深入解析了如何利用SGDC驱动的轻量级入侵检测系统保护IoT设备安全。通过实战指南,详细阐述了SGDC模型在资源受限环境下的优势,并结合特征选择技术优化模型性能,实现高效、低耗的异常流量检测,为物联网安全部署提供了一套可行的解决方案。

weixin_29192211的博客 350

fork() 问题

前两天有人问了个关于Unix的fork()系统调用的面试题,这个题正好是我大约十年前找工作时某公司问我的一个题,我觉得比较有趣,写篇文章与大家分享一下。这个题是这样的: 题目:请问下面的程序一共输出多少个“-”? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include #include

knight 1429

Cursor+Apifox MCP Server实战:5分钟搞定API自动化测试用例生成

本文详细介绍了如何利用Cursor IDE与Apifox MCP Server,在5分钟内将API文档自动转化为高质量的自动化测试用例。通过配置MCP Server建立数据桥梁,开发者可直接用自然语言指令,让AI基于真实接口规范生成可立即执行的pytest测试代码,大幅提升接口测试效率,特别适合快节奏的SaaS项目。

ooo22的博客 533

fork函数详解(fork就是分叉的意思, 很形象)

转载地址:http://blog.sina.com.cn/s/blog_7582409f0100v6cp.html

认知 行动 坚持 1万+

实战对比:VINS和ORBSLAM3在无人机避障中的表现(含实测数据)

本文通过实战测试,深度对比了VINS和ORBSLAM3两种主流视觉SLAM算法在无人机避障中的表现。测试聚焦于光照变化、动态遮挡和快速运动三大挑战,提供了详细的实测数据与性能分析。结果表明,VINS在计算效率和实时性上占优,而ORBSLAM3在定位精度和地图管理方面更稳健,为不同应用场景下的工程选型提供了清晰依据。

醉三国 627

某讯天御滑块验证码逆向实战:从参数解析到环境对抗

本文详细解析了某讯天御滑块验证码的逆向工程实战技巧,从关键参数解析到浏览器环境模拟对抗。重点介绍了collect、eks等参数的逆向思路,以及如何通过puppeteer等工具补全环境检测,帮助开发者有效突破验证码防护。文章还提供了常见错误解决方案和性能优化建议,是验证码逆向领域的实用指南。

weixin_29325007的博客 437

fork()请问下面的程序一共输出多少个“A”?多少个"-"?

fork() 题目:请问下面的程序一共输出多少个“-”? #include #include #include int main(void) { int i; for(i=0; i&amp;lt;2; i++){ fork(); printf(&quot;-&quot;); } return 0; } 解析:一共输出8个。 首先程序一开始,bash产生一个进程P1执行此程序,P1...

csdn_kou的博客 1971

facebook协议

支持同时登录多个Facebook账号,按照关键词采集小组地址,群发小组,批量添加推荐人,群发推 荐人消息,采集个人Facebook用户,群发用户私信,群发主页评论。通过客服台管理功能,和粉丝互动聊天,通过话术快捷回复,自动翻译聊天记录。通过FaceBook小组采集小组成员id,或者通过FaceBook个人主页,采集主页上粉丝批量操作已FaceBook账号添加推荐热,可以指定添加某个国家的推荐人,可以设置每个账号添加推荐人个数去重模式:所有的FaceBook账号不添加重复的推荐人。

2503_90751938的博客 952

从多进程函数fork解读linux系统行缓冲与全缓冲

先说下fork函数:linux系统中,一个现有的进程可以调用fork函数创建一个新的进程。由fork创建的新进程成为子进程(child process)。fork函数被调用一次,但是返回两次。两次返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程ID。子进程和父进程分别继续执行fork调用之后的命令。子进程是父进程的副本(注意是副本,父、子进程不共享资源)。不同的返回值可用于区

学历只能代表过去,能力代表着现在,而学习代表的是未来。 1783

【Diffusion分割】医学图像分割中去噪扩散技术

扩散模型(DPM)在图像生成方面表现出了卓越的性能,其性能往往优于其他生成模型。自其问世以来,强大的噪声-图像去噪管道已被扩展到各种判别任务中,包括图像分割。在医学成像中,图像往往是大型三维扫描图像,由于内存消耗大、迭代采样过程耗时,使用 DPM 对一幅图像进行分割的效率极低。在这项工作中,我们提出了一种(LDSeg),可在潜空间中执行扩散,用于医学影像分割。我们。潜空间条件扩散不仅能确保对多标签对象进行精确的 n-D 图像分割,还能缓解基于 DPM 的传统分割法的主要潜在问题:(。

qq_43583311的博客 1171

构建基于知识图谱的金融风险关联网络可视化系统

知识图谱是一种用于表示实体及其关系的图形结构,能够将分散的数据组织成易于理解和查询的形式。语义性:通过实体和关系的描述,赋予数据语义。结构化:以图的形式组织数据,便于计算机处理。动态性:支持实时更新,能够反映数据的最新状态。风险关联网络是指将金融风险事件、实体及其关系以图形形式表示的网络。关联性:能够展示风险事件之间的相互影响。动态性:能够实时反映风险变化。可视化:便于金融从业者直观理解风险分布。可视化系统是指通过图形界面展示数据或信息的系统。提供直观的数据显示。帮助用户快速理解复杂数据。

AI天才研究院 1057

通过fork函数解读linux系统行缓冲与全缓冲

基于流的操作最终会调用read或者write函数进行I/O操作。为了使程序的运行效率最高,流对象通常会提供缓冲区,以减少调用系统I/O库函数的次数。 1、全缓冲 。全缓冲指的是系统在填满标准IO缓冲区之后才进行实际的IO操作;注意,对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。 2、行缓冲 。在这种情况下,标准IO在输入和输出中遇到换行符时执行IO操作;注意,当流涉及终端的时候,通常

CharliePeng的专栏 1001

漏洞挖掘之工具配置

本文主要讲解burp工具的插件安装。

qq_64775230的博客 3273

从一个fork()实例理解全缓冲与行缓冲

之前一直对无缓冲、行缓冲、全缓冲不太感冒, 然后最近在《UNIX环境高级编程》上看到这样一个例子,感觉挺好的拿来给没看过的小伙伴们看看:、 #include #include int globvar = 6; char buf[] = "a write to stdout\n"; int main() { int var; pid_t pid; var

Everlasting2016的博客 801

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

八_进程控制2 - fork()详解,与行缓冲,全缓冲的联系

1 进程标识符 pid 2 类型是 pid_t 3 命令ps 4 进程号是顺次向下使用 5 getpid() getppid() 6 进程的产生: fork(); duplicating 拷贝!! vfork(); getpid()/getppid NAME getpid, getppid - get process identification SYNOPSIS #include <sys/types.h> #include <unistd.h> pid_t getpid

奶牛养殖场小马 437

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

关于fork和行缓冲的问题

http://shentar.me/%E5%85%B3%E4%BA%8Efork/

wuxianglonghaohao的专栏 716

fork函数的坑

#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { int i; for(i=0; i<2; i++) { fork(); printf("A"); } return 0; } 首先这个题问,产生了多少个进程,打印出来了多少个A 行缓冲概念: 什么是行缓冲? 当输入输出遇到换行符的这类缓冲定义为行缓冲。标准输入和标准输

flf1234567898的博客 507

printf 缓冲区问题

昨天在做Linux实验的时候,后面的同学发现一个很差异的现象!废话不说,先贴代码!             就是简单的fork小程序,简化之后的代码如下: [cpp] view plaincopyprint? #include    #include    #include    #include       in

leokelly001的专栏 830

标准IO缓冲与fork问题

系统函数read和write是不带缓冲的,而c的标准io函数是带缓冲的, (1)当io函数与stderr相连时 是不带缓冲的 (2)当与stdin和stdout相连是行缓冲的(即遇到换行符就输出) (3)与其他的相连都是全缓冲的(缓冲区满了才输出) 可以用一个小例子试一下,参考 《unix环境高级编程》 8.1 # include # include int globvar = 6;

曾经最动心的专栏 553

Linux中fork与输出缓冲区的交互问题解析

在Linux系统编程中,进程管理(fork)和I/O缓冲机制是两大基础技术。fork()通过写时复制机制高效创建子进程,而标准I/O库则利用缓冲区提升性能。当这两者结合时,由于子进程会复制父进程的未刷新缓冲区,可能导致日志重复、输出丢失等问题。理解全缓冲、行缓冲和无缓冲三种模式的区别,掌握fflush和setvbuf等关键函数的使用,对开发多进程应用尤为重要。本文通过典型场景分析,揭示了分布式系统中日志错乱等问题的根源,并给出工程实践中的解决方案。

weixin_34292402的博客 425

进程创建与缓冲区:fork 经典问题

系统调用 write() 输出到终端/文件,屏幕输出hello,由内核打印到屏幕。由于exit正常退出并刷新,printf的内容才从缓冲区中刷新出去。//少了\n会有什么影响。复制父进程:子进程获得父进程数据段、堆栈段的完整副本。继承资源:子进程继承父进程的文件描述符、环境变量等。//不刷新缓冲区,程序直接退出。子进程从 fork() 调用的下一条指令开始执行。运行现象:先等待3秒,程序退出才输出hello。父子进程是独立的,有各自的地址空间。}//会输出多少个A;}//会输出多少个A;

Ok616的博客 350

执行fork后printf的输出问题

int main(void) { printf("123456\n"); if(fork()) exit(1); else exit(1); }终端上输出:~$ ./a.out123456输出重定向到文件后读取文件:~$ ./a.out > test~$ cat test123456123456 原因:当直接由终端输出时,此时标准io采用行

qq_36314651的博客 1465

fork与缓冲区问题

fork是unix下创建子进程的函数 pid_t fork(void); //创建一个进程,父进程返回值为子进程pid,子进程返回值为0 当我们运行如下代码时, #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<sys/wait.h> #include<errno.h> #include<stdio.

tgkyrie的博客 482

【Linux】理解缓冲区

【Linux】理解缓冲区,缓冲区是什么?为什么有缓冲区?缓冲区在哪里?如何去理解缓冲区?

weixin_60478154的博客 2300
上一篇: Linux终端进程管理必备命令
下一篇: 性能调优
IT_Linux
博客等级 码龄14年 31粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值