2019-2020-1 20199310《Linux内核原理与分析》第七周作业

1.问题描述

在前面的文章中,学习了系统调用system_call的处理过程,在MenuOS中运行getpid命令,通过gdb跟踪调用time函数的过程,并分析system_call代码对应的工作过程,本文将对Linux系统如何创建一个新进程进行追踪。

2.解决过程

2.1 进程的描述

操作系统内核实现操作系统的三大管理功能:进程管理,内核管理和文件系统,其中最核心的功能是进程管理。
在操作系统原理中,我们通过进程控制块PCB描述进程,通常采用一个数据结构struct task_struct来描述进程,其中比较常见的属性如state是进程状态,常见状态有就绪态,运行态和阻塞态,其运行过程如图所示:

2.2 gdb跟踪调用fork函数的过程

先对实验楼环境进行修改,删除menu,在github上克隆一份新的,并且把test.c覆盖,在menu下执行make rootfs,编译运行结果如下所示:


退出menu目录,在LinuxKernel目录下执行

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s

然后横屏打开另一个终端,进行gdb追踪

file linux-3.18.6/vmlinux
target remote:1234

然后对sys_clone,do_fork,dup_task_struct,copy_process,copy_thread和ret_from_fork设置断点:

在gdb中continue执行到第一个断点SyS_clone处;

执行至第2个断点do_fork创建新进程:


单步执行调试,会停留在第4个断点copy_pocess:

单步执行调试,会停留在第3个断点,在copy_process中调用dup_task_struct:

继续执行调试,会停留在第5个断点copy_thread和第6个断点ret_from_fork上,父进程显示:

单步跟踪,选中刚才创建的子进程的PCB,设置的ip进入ret_from_fork函数调度子进程语句,再重置标志寄存器eflags为0x0202,再跳转至syscall_exit退出:


最终子进程显示结果:

3.总结

本文主要学习了Linux内核系统创建新子进程,并通过gdb和代码分析了调用过程。一般情况下,调用系统调用需在当前内核linux-3.18.6/arch/x86/syscalls/syscall_32.tbl中查找调用号,库函数sys_fork是用户态创建子进程的系统调用,此外可能会使用到sys_vfork sys_clone系统调用,但是这三个系统调用都会调用do_fork函数,本文中使用了sys_clone。do_fork会调用copy_process来复制父进程的资源给子进程。在copy_process中有各种函数来进行复制初始化工作。完成各项工作之后会执行ret_from_fork,这是子进程的起点,运行,子进程可以执行并显示在终端中。总结来讲,进程的创建过程大致是赋值进程描述符,复制其他进程资源,分配子进程的内核堆栈并对内核堆栈关键信息进行初始化。

posted @ 2019-11-02 09:29  20199310娄豪  阅读(146)  评论(1编辑  收藏  举报