Fork——分道扬镳的开始

Fork——分道扬镳的开始

刺猬@http://blog.csdn.net/littlehedgehog





在copy_process的函数中有这样一段代码:

p->tss.eax = 0 ;    

赵博注释道: 这就是当fork()返回时新进程会返回0的原因所在! 呃,很多人不明白这段注释含义,fork返回0?我怎么没看见fork在新进程返回了? 这里我介绍下我的看法权当是抛砖引玉,以后有新手路过浏览拙文,若有一丝领悟,此文也达到它目的了。

话说这个fork返回值问题,赵博论坛(http://oldlinux.org)也有不少人讨教。其实追根溯源,fork调用还得到unix那个年代说起。

且看代码:

#include <stdio.h>
#include 
<unistd.h>
int  main()
{
    fork();
    printf(
"hello/n"
);
    
return 0
;
}

试问,此程序打印结果?

Fork——分道扬镳的开始

打印出两个helllo,若是初次调用fork可能有稍许惊讶,不过细细想来便知: 当前进程运行到fork时候,产生了一个新进程,我们知道新的进程几乎全部是拷贝父进程所有内容,最为重要的便是进程的TSS段。cs、eip均是拷贝的父进程内容。请看这段内核代码(部分):

 

        p -> tss.back_link  =   0 ;
    p
-> tss.esp0  =  PAGE_SIZE  +  ( long ) p;    
    p
-> tss.ss0  =   0x10 ;
    p
->tss.eip =  eip;
    p
-> tss.eflags  =  eflags;
    p
->tss.eax = 0 ;        
    p
-> tss.ecx  =  ecx;
    p
-> tss.edx  =  edx;
    p
-> tss.ebx  =  ebx;
    p
-> tss.esp  =  esp;    
    p
-> tss.ebp  =  ebp;
    p
-> tss.esi  =  esi;
    p
-> tss.edi  =  edi;
    p
-> tss.es  =  es  &   0xffff ;
    p
->tss.cs = cs & 0xffff ;
    p
-> tss.ss  =  ss  &   0xffff ;
    p
-> tss.ds  =  ds  &   0xffff ;
    p
-> tss.fs  =  fs  &   0xffff ;
    p
-> tss.gs  =  gs  &   0xffff ;
    p
-> tss.ldt  =  _LDT(nr);
    p
-> tss.trace_bitmap  =   0x80000000 ;

注意我加粗的两句,分别是给子进程cs、eip赋值的,全部是父进程相对应的值。那么当子进程运行的时候,eip还是指向的是父进程的代码,也就是说子进程运行时仍执行的是父进程代码,即是打印hello。那么我们上面可以看到父进程和子进程同时会执行printf这条代码,难怪会有两行hello的打印。

Fork的调用问题我们就探讨到这儿,下面我们来看看赵博为什么说这就是当fork()返回时新进程会返回0的原因所在!

由上面的例子我们可以看到其实当fork调用后,父进程和子进程都会按照原来的代码流执行下去。我们来设想一下: 现在假如是父进程在调用fork后,父进程执行,fork的返回值就是子进程的进程号。fork这段代码是段嵌入式汇编宏函数,也就是syscall0. 大家可以参照《完全剖析》p235,恕不细表。而如果是子进程被调度的话,我们看到由于前面我们设置了tss:

p->tss.eax = 0 ;    

此时的tss中的eax设为了0,一旦子进程被调度,cpu会自动加载tss,然后eax会被自动设为0,而一般情况下我们是把eax当作程序的返回值存放地点的,所以这里类似于返回了0

这样fork在父进程返回的是子进程的进程号,而在子进程“返回”的是0。我们就可以根据此区分当前是父进程在运行,还是子进程在运行了。比如下例:

 

#include <stdio.h>
#include 
<unistd.h>
int  main()
{
    pid_t pid;
    pid
=
fork();
    
if (pid==0
)
    
{
        printf(
"child "
);
    }

    printf(
"parent ");
    
return 0
;

}

你可能感兴趣的:(fork)