分析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函数,具体的过程:
- 复制一个PCB——task_struct
-
要给新进程分配一个新的内核堆栈
ti = alloc_thread_info_node(tsk, node); tsk->stack = ti; setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈
-
要修改复制过来的进程数据,比如pid、进程链表等,见copy_process内部。
*childregs = *current_pt_regs(); //复制内核堆栈childregs->ax = 0; // 子进程的fork返回0p->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可执行程序。