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

攥写人:于涵  学号:20132119

( *原创作品转载请注明出处*)

( 学习课程:《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-100

课后问题:

创建的新进程是从哪里开始执行的:ret_from_fork
*childregs = *current_pt_regs();  复制内核堆栈(复制的pt_regs,是SAVE_ALL中系统调用压栈的那一部分。)

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

 ip指向的是ret_from_fork,所以是从这里开始执行的。

 

实验过程:

删除原来menu,clone新的,覆盖test.c

 

make rootfs运行新内核,测试Fork

 

 

用qemu开启虚拟机,使用-s -S冻结

 

开启另一指令行窗口,开启gdb

载入符号表,配置端口

设置断点

跟踪结果

 

知识点:

 

 fork函数,具体的过程

 

  1. 复制一个PCB——task_struct
  2. 要给新进程分配一个新的内核堆栈

        ti = alloc_thread_info_node(tsk, node);
        tsk->stack = ti;
        setup_thread_stack(tsk, orig);       //这里只是复制thread_info,而非复制内核堆栈
  3. 要修改复制过来的进程数据,比如pid、进程链表等,见copy_process内部。

    *childregs = *current_pt_regs();          //复制内核堆栈
    childregs->ax = 0;                        // 子进程的fork返回0
    
    p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
    p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址    

 

sys_fork,sys_vfrok,sys_clone,最终执行的都是do_fork

 

操作系统内核三大功能:

  进程管理,内存管理,文件系统

最核心的是进程管理

为了管理,首先要对每一个进程进行描述。进程描述符提供了所有内核需要了解的信息。

进程控制模块:task_struct

  next_task,prev_task进程链表的管理

  tty_struct控制台

  fs_struct文件系统描述

  file_struct打开的文件描述符

  mm_struct内存管理的描述

  signal_struct信号的描述

进程的创建概括以及fork()一个进程

    Cpu_idle启动两个线程:(0号进程是所有线程的祖先)

    Kernel_init用户态的进程启动,所有用户态进程的祖先(1号进程是所有进程的祖先)

    Kthreadd所有线程的祖先

    在shell命令行创建进程的本质一样:先复制一份进程描述符,0号进程是手工写进代码的,1号进程复制0号的pcb,然后根据1号进程的需要把它的pid等等信息修改掉,再加载一个init可执行程序。