Linux内核创建一个新进程的实验

    陈铁  + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000


    Linux内核对进程管理是操作系统的重要任务之一。此次实验就是了解内核创建一个新进程的大致过程。为了简单,使用fork再用户态创建一个进程。代码如下:

#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");
    }
}

    在虚拟机环境中运行情况如下图:

技术分享

技术分享

以下使用gdb调试一下,在进程创建过程中的几个关键函数出设置断点。

技术分享

在系统启动过程走了些弯路,设置断点的这几个函数都是系统创建进程所必须的关键部分,所以启动过程中do_fork,copy_process,copy_thread不断的多次出现,我只好暂时使断点失效,才让menuos顺利启动到命令提示符。disable breakpoints 1 2 3 4 5 6.

执行fork命令,停在了断点SyS_clone处,单步执行,定在了断点do_fork处。经过几行代码,


p = copy_process(clone_flags, stack_start,stack_size,chile_tidptr, NULL,trace);

停在断点copy_process.在执行几行代码,如下:

p = dup_task_struct(current);

继续执行,断点arch_dup_task_struct停住。

连续n命令后可以看到子进程的初始化过程:

技术分享

程序执行断在copy_thread后如下:

技术分享

执行finish,及continue命令,进入了子进程执行的起点ret_from_fork.

技术分享

执行c命令,主要过程基本结束。


    总结,创建一个新进程在内核中的执行过程大致如下

        1.使用系统调用SyS_clone(或fork,vfork)系统调用创建一个新进程,而且都是通过调用do_fork来实现进程的创建;
        2.Linux通过复制父进程PCB--task_struct来创建一个新进程,要给新进程分配一个新的内核堆栈;

        3.要修改复制过来的进程数据,比如pid、进程链表等等执行copy_process和copy_thread
        4.p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
          p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址

本文出自 “StudyPark” 博客,请务必保留此出处http://swordautumn.blog.51cto.com/1485402/1630810

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。