Chinaunix首页 | 论坛 | 博客
  • 博客访问: 134660
  • 博文数量: 47
  • 博客积分: 2405
  • 博客等级: 大尉
  • 技术积分: 385
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-28 09:33
文章分类

全部博文(47)

文章存档

2014年(5)

2012年(5)

2011年(7)

2009年(30)

我的朋友

分类: C/C++

2009-08-16 01:27:05

fork问题的经典理解


main()
  
{
      
pid_t pid;
      
if(pid=fork()<0)
      
{
          
printf("error!");
      
}
      
else
      
{
            
if(pid==0)
            
printf("a\n");
            
else
            
printf("b\n");
      
}
  
}

结果是返回a,b或者b,a   
  因为fork调用将执行两次返回分别从子进程和父进程返回   
  由于父进程和子进程无关,父进程与子进程都可能先返回   
    
  在看一个程序

main()
  
{
      
pid_t a_pid,b_fork;
      
if(a_pid=fork()<0)
      
{
          
printf("error!");
      
}
      
else
      
{
            
if(a_pid==0)
            
printf("b\n");
            
else
            
printf("a\n");
      
}
    
      
if(b_pid=fork()<0)
      
{
          
printf("error!");
      
}
      
else
      
{
            
if(b_pid==0)
            
printf("c\n");
            
else
            
printf("a\n");
      
}
  
}
    

如果是创建两个进程则出现结果   
  b   
  c   
  a   
  a   
  c   
  a  

事 实上,理解fork()的关键在于它的返回点在哪里。fork最特殊的地方就在于他有两个甚至三个返回值,注意是同时返回两个值。其中pid=0的这个返 回值用来执行子进程的代码,而大于0的一个返回值为父进程的代码块。第一次fork调用的时候生叉分为两个进程,不妨设为a父进程和b子进程。他们分别各 自在第二次fork调用之前打印了b和a各一次;在第一次叉分的这两个进程中都含有   

if(b_pid=fork()<0)
  
{
  
printf("error!");
  
}
  
else
  
{
  
if(b_pid==0)
  
printf("c\n");
  
else
  
printf("a\n");
  
}
  
}

这段代码。很明显,a父进程和b子进程在这段代码中又各自独立的被叉分为两个进程。这两个进程每个进程又都打印了a,c各一次。到此,在程序中总共打印三次a两次c和一次b。总共6个字母。   
  注:在第一次叉分为两个进程的时候父子进程含有完全相同的代码(第二次仍然相同),只是因为在父子进程中返回的PID的值不同,父进程代码中的PID的值大于0,子进程代码中的值等于0,从而通过if这样的分支选择语句来执行各自的任务。

 

我做如下修改 


 main
()
  
{
      
pid_t pid;
      
if(pid=fork()<0)
      
{
          
printf("error!");
      
}
      
else
      
{
            
if(pid==0)
            
printf("a\n");
            
else
            
printf("b\n");
      
}
  
}
  结果是返回a
,b或者b,a
  因为fork调用将执行两次返回分别从子进程和父进程返回
  由于父进程和子进程无关,父进程与子进程都可能先返回
    
  在看一个程序
    
  main
()
  
{
      
pid_t a_pid,b_fork;
      
if(a_pid=fork()<0)
      
{
          
printf("error!");
      
}
      
else
      
{
            
if(a_pid==0)
            
printf("b\n");
            
else
            
printf("a\n");
      
}
    
      
if(b_pid=fork()<0)
      
{
          
printf("error!");
      
}
      
else
      
{
            
if(b_pid==0)
            
printf("c\n");
            
else
            
printf("a\n");
      
}
  
}
    
  如果是创建两个进程则出现结果
  b
  c
  a
  a
  c
  a

事实上,理解fork
()的关键在于它的返回点在哪里。fork最特殊的地方就在于他有两个甚至三个返回值,注意是同时返回两个值。其中pid=0的这个返回值用来执行子进程的代码,而大于0的一个返回值为父进程的代码块。第一次fork调用的时候生叉分为两个进程,不妨设为a父进程和b子进程。他们分别各自在第二次fork调用之前打印了b和a各一次;在第一次叉分的这两个进程中都含有
  
if(b_pid=fork()<0)
  
{
  
printf("error!");
  
}
  
else
  
{
  
if(b_pid==0)
  
printf("c\n");
  
else
  
printf("a\n");
  
}
  
}
  这段代码。很明显,a父进程和b子进程在这段代码中又各自独立的被叉分为两个进程。这两个进程每个进程又都打印了a
,c各一次。到此,在程序中总共打印三次a两次c和一次b。总共6个字母。
  注:在第一次叉分为两个进程的时候父子进程含有完全相同的代码(第二次仍然相同),只是因为在父子进程中返回的PID的值不同,父进程代码中的PID的值大于0,子进程代码中的值等于0,从而通过if这样的分支选择语句来执行各自的任务。

 

我做如下修改

#include <unistd.h>;
#include <sys/types.h>;

main
()
{
        
pid_t pid;
        
printf("fork!"); // printf("fork!n");

        pid
=fork();

        
if (pid < 0)
                
printf("error in fork!");
        
else if (pid == 0)
                
printf("i am the child process, my process id is %dn",getpid());
        
else
                
printf("i am the parent process, my process id is %dn",getpid());
}

结果是  
[root@localhost c]# ./a.out  
fork!i am the child process, my process id is 4286  
fork!i am the parent process, my process id is 4285 

但我改成printf("fork!n");后,结果是 
[root@localhost c]# ./a.out 
fork!  
i am the child process, my process id is 4286  
i am the parent process, my process id is 4285 

为什么只有一个fork!打印出来了?上一个为什么有2个?

printf("AAAAAAAA");//print 一次;   这里会print 2次 
如果你将 printf("AAAAAA") 换成 printf("AAAAAAn")   那么就是只打印一次了. 
主要的区别是因为有了一个 n  回车符号 
这就跟Printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有实际的写到屏幕上 
但是,只要看到有 n 则会立即刷新stdout,因此就马上能够打印了. 
运行了printf("AAAAAA") 后, AAAAAA 仅仅被放到了缓冲里,再运行到fork时,缓冲里面的 AAAAAA 被子进程继承了 
因此在子进程度stdout缓冲里面就也有了 AAAAAA. 
所以,你最终看到的会是 AAAAAA 被printf了2次!!!! 
而运行 printf("AAAAAAn")后, AAAAAA 被立即打印到了屏幕上,之后fork到的子进程里的stdout缓冲里不会有 AAAAAA 内容 
因此你看到的结果会是 AAAAAA 被printf了1次!!!!
阅读(2079) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~