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个“-”。 要讲清这个题 阅读详情

相关推荐

NLP-Beginner 任务一:基于机器学习的文本分类(超详细!!)

NLP-Beginner 任务一:基于机器学习的文本分类传送门一. 介绍1.1 任务简介1.2 数据集1.3 流程介绍二. 特征提取2.1 词袋特征(Bag-of-word)2.2 N元特征 (N-gram)三. 最优化求解3.1 Softmax回归介绍3.2 损失函数3.3 梯度下降3.4 学习率四. 代码及实现4.1 实验设置4.2 结果展示4.3 代码新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、

0oTedo0 9931

fork() 问题

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

knight 1429

致远OA系统表单相关操作记录(一)

致远OA系统表单相关操作

weixin_59666050的博客 6099

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

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

认知 行动 坚持 1万+

ORCAD原理图关联封装时出现ERROR(ORCIS-6245)、ERROR(ORCIS-6013)问题

1、当你进行如下操作时: 系统先是提示你出现ERROR(ORCIS-6245)然后再确定后再出现ERROR(ORCIS-6013)问题 是由于你的数据库的路径不对。 具体操作方法如下:1、先找到你的CAPTURE.INI文件。 2、用记事本打开CAPTURE.INI。找到下图路径 3、在你的Orcad capture CIS原理图软件中点击 Options------>CIS con...

weixin_42304393的博客 2万+

搭建微信机器人的方案都在这了!

功能超级强大,虽不支持二次开发,但已有的功能足够个人使用,可惜官方作品已被腾讯告死,好在市面上还流落着不少破解版,有需要的自行搜索。可惜的是,微信官方已不准许新的微信号再使用 web 登录,这就直接从源头扼杀了 web 协议的微信机器人,虽说老的微信号还是能凑合着用,不过部分功能也受限。所以,这些都属于 PC 端的微信机器人。无论是 PC 端还是手机端,用 hook 方式实现的最大缺点就是要和某一个版本的微信客户端进行绑定,如果框架本身不对最新版本的微信适配,那使用的时候就无法升级到最新版本的微信。

weixin_47246330的博客 1万+

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

英飞凌TC3xx之一起认识GTM系列(六)如何实现GTM与VADC关联的配置

本文给出了GTM与EVADC之间关联的细节,并通过两个实例分别说明了如何对寄存器进行配置。

无所适从的我的博客 2932

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

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

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

利用 Python 爬虫进行舆情监测的实战方法

舆情监测是指对互联网上的公众舆论进行监测和分析的过程。它可以帮助企业和组织了解公众对其品牌、产品或服务的看法,以及市场竞争情况。通过舆情监测,企业可以及时发现潜在的问题和机会,从而做出相应的决策。通过本实战案例,我们了解了如何利用 Python 爬虫进行舆情监测的整个流程。从数据采集到数据分析,再到可视化展示,每一步都提供了详细的代码示例和注释。希望这些方法和技巧能够帮助你在实际工作中更好地进行舆情监测,从而为企业的决策提供有力的支持。wordcloud。

u014481728的博客 1054

48、量子系统中的信源编码

本文深入探讨了量子系统中的信源编码理论与应用,详细介绍了盲编码与可见编码、定长编码与变长编码四种主要信源编码方案。文章从经典信源编码出发,对比分析了量子场景下的压缩特性,并系统性地阐述了量子定长信源编码的构建方法及相关定理证明。同时,讨论了通用量子定长信源编码的设计思路及其在实际应用中的优势与挑战。通过理论分析与实验进展的结合,为量子信息存储、传输和处理提供了重要的理论基础和技术支持。

m2n3b4v5c6的博客 100

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

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

CharliePeng的专栏 1001

Access查询中的Dlookup函数的妙用

在Microsoft Access中,处理和分析数据的过程中,常常会遇到需要根据条件从其他记录中提取特定数据的情况。这时候,Dlookup函数就成了开发者和数据分析师的得力助手。今天我们将通过一个具体的实例,详细探讨如何利用Dlookup函数来解决复杂的查询问题。

m0_62153576的博客 294

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

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

Everlasting2016的博客 801

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

八_进程控制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

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

关于fork和行缓冲的问题

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

wuxianglonghaohao的专栏 716

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

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、付费专栏及课程。

余额充值