分析Linux内核创建一个新进程的过程

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char * argv[])
{
    int pid;
    /* fork another process */
    pid = fork();
    if (pid < 0) 
    { 
        /* error occurred */
        fprintf(stderr,"Fork Failed!");
        exit(-1);
    } 
    else if (pid == 0) 
    {
        /* child process */
        printf("This is Child Process!\n");
    } 
    else 
    {  
        /* parent process  */
        printf("This is Parent Process!\n");
        /* parent will wait for the child to complete*/
        wait(NULL);
        printf("Child Complete!\n");
    }
}

他的运行结果如下图:这里写图片描述
上面的程序大家应该都能看懂。需要注意的是pid = fork();执行过后返回值,如果pid为0,则代表子进程,如果pid不为0且不是负数,则代表父进程。运行结果图中返回的结果是子进程和父进程都运行结束之后的结果,并不是一个进程同时走到了 if 语句中的两个条件。
子进程在复制父进程的内核堆栈的时候只是复制了其中的一部分内容,并不是完全的copy。

ti = alloc_thread_info_node(tsk, node);
tsk->stack = ti;
setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈

这样就保证了子进程在返回时执行自己应该执行的位置,而不是从main()重新开始执行。如果从main()重新执行的话,fork()就永无休止了。如下代码能够帮助我们进一步了解子进程返回后的执行位置:

*childregs = *current_pt_regs(); //复制内核堆栈
childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!

p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址

可见,sp和ip在子进程中都换成了自己的值,而不是父进程的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值