QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1343|回复: 17

这个程序的结果为什么是这样?

[复制链接]
发表于 2005-4-29 13:07:59 | 显示全部楼层 |阅读模式
程序如下:
#include "stdio.h"
main()
{
  int p1,p2;
  while((p1=fork())==-1); /*创建子进程p1 */
  putchar('b');

  while((p2=fork())==-1); /*创建子进程p2*/
  putchar('a');
}
执行的结果竟然是输出babababa  ,这是为什么呢?“父进程和子进程的程序完全相同”

这句话是什么意思,是从调用fork()的地方开始完全相同还是从main函数的地方都相同

啊。我本来以为父进程创建了子进程p1,然后它们都会输出b,然后父进程和刚创建的子进
程p1又都会创建子进程p2,分别各输出一个a共4个a,然后结果中只能是2个b和4个a ,可
是结果完全不是这样。  哪位高手可以帮解释一下吗? 谢谢。
发表于 2005-4-29 13:19:40 | 显示全部楼层
没判断父进程还是子进程
回复

使用道具 举报

 楼主| 发表于 2005-4-29 13:31:02 | 显示全部楼层
对不起,没明白你的意思
回复

使用道具 举报

发表于 2005-4-29 15:38:53 | 显示全部楼层
输出缓冲区字符发生混乱。[code:1]#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>

int main()
{
int p1,p2;

p1=fork();

while(p1==-1);
putchar('b');
fflush(stdout);

p2=fork();

while(p2==-1);
fflush(stdout);
putchar('a');
printf("\n");
return 0;
}
[/code:1]
回复

使用道具 举报

 楼主| 发表于 2005-4-29 17:07:58 | 显示全部楼层
如果两个子进程要做的工作里面都有printf 和scanf的时候,子进程和父进程的输出和输入会交替交叠在一起。这是什么原因呢?
回复

使用道具 举报

发表于 2005-4-29 21:07:43 | 显示全部楼层
我想,对于进程控制,我们首先必需注意这样两个基本意识:

一. 与终端连接的缓冲区是什么类型(全缓冲,行缓冲,无缓冲),如果用putchar,缓冲类型就是无缓冲

模式,即接收一个字符就立马输出,用printf就是行缓冲了,

二. 子进程会继承父进程的enviroment(环境),这包括数据段,堆栈等

好,现在来分析上面的代码,父进程运行下来先建立子进程p1,然后输出b, p1运行下来也会有b输出,

父进程再下来会建立p2,p2继承父进程的环境,这时候缓冲区有b,p2 接收到了,立马输出,然后同

父进程一齐下来又有两个a输出,前面的p1下来会建立子进程p3,p3继承p2的环境,也会有b输出

然后与p2一齐下来输出两个a,所以就有4个b4个a,当然具体的是babababa还是bbaabbaa或别的

什么输有出,都是有可能的,这要看具体系统是怎么安排的,
回复

使用道具 举报

发表于 2005-4-29 21:09:54 | 显示全部楼层
大家把上面的代码中的putchar改成printf,看看会有什么结果,

然后用继承和缓冲去解释
回复

使用道具 举报

发表于 2005-4-29 21:35:20 | 显示全部楼层
楼上的说得好   
不过如果putchar是无缓冲的话,就不应该有4个b了,对吧,因为父进程输出之后,p2的缓冲区中不应该有b。而且看apue说类svr4系统除了标准错误输出之外都是行缓冲,这也和楼主程序输出相吻合。不知linux的默认缓冲是不是这样的。
至于输出有规律,是因为在一个时间片内进程有足够的时间输出ba。所以不会乱序。
回复

使用道具 举报

发表于 2005-4-30 09:09:49 | 显示全部楼层
一,父进程输出后,P2的缓冲里有b,因为无缓冲并不是说接收一个字符缓冲区

就自动清掉了,只是立即输出到终端而已,东西还在,所以应该还是4个b。

二,至于次序问题,肯定是有可能乱序的,因为你不能肯定4条进程线下来,

哪个先到,哪个后到,这就具体要看进程调度是怎样的了
回复

使用道具 举报

发表于 2005-4-30 10:20:35 | 显示全部楼层
既然无缓冲就不应该写入缓冲区,所以无缓冲的情况下应该是两个b,所以putchar还是属于行缓冲。
用printf和pubchar的效果是一样的。我的gcc3.3.5,kernel2.6.11.7.
如果在最前面加上[code:1]  setvbuf(stdout,0,_IONBF,0);[/code:1]将输入缓冲模式设为无缓冲就可以等到正确结果。这证明了putchar也是行缓冲。
回复

使用道具 举报

发表于 2005-5-1 20:11:56 | 显示全部楼层
我觉得,无缓冲并不是输出不用缓冲区,而是接收一个字符立即输出,所以缓冲

区大小是一个字节,行缓冲至少是两个字节,任何与终端连接的进程不可能

直接把数据送给终端的,总得在内存待一会
回复

使用道具 举报

发表于 2005-5-1 21:39:09 | 显示全部楼层
直接read,write保险!
回复

使用道具 举报

发表于 2005-5-1 21:47:11 | 显示全部楼层
在内存中是要呆,不过无缓冲是在内核缓冲区呆,用户级是没有缓冲的。
回复

使用道具 举报

发表于 2005-5-2 10:03:27 | 显示全部楼层
这就是了,子进程在继承父进程时就应该会把这一个字节的缓冲拷贝过去
回复

使用道具 举报

发表于 2005-5-2 10:48:02 | 显示全部楼层
[quote:d0d16fab5d="hhuzhang"]这就是了,子进程在继承父进程时就应该会把这一个字节的缓冲拷贝过去[/quote]那你怎么解释putchar和printf出现一样的结果,但设置了无缓冲之后只有2个b了?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-6 03:35 , Processed in 0.205506 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表