2023-2024-1 20232806《Linux内核原理与分析》第七周作业

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

一、实验过程

1、task_struct 数据结构
Linux系统中的每个进程都有一个名为task_struct的数据结构,它相当于“进程控制块(PCB)”,用于表示和管理每个正在运行的进程(或任务)。task_struct结构体被定义在<include/linux/sched.h>中,是非常重要的数据结构。它包含了有关进程的各种属性和状态信息,以便内核能够有效地管理和调度它们,该结构体的定义如下所示。

struct task_struct {
    volatile long state;  // 进程状态
    void *stack;          // 进程堆栈指针
    unsigned int flags;   // 进程标志
    struct list_head tasks;  // 进程链表
    pid_t pid;            // 进程ID
    pid_t tgid;           // 进程组ID
    struct mm_struct *mm; // 内存管理结构
    struct files_struct *files;  // 文件描述符表
    // ... 其他字段和信息 ...
};

2、分析 fork 函数对应的内核处理过程 sys_clone
fork 函数在Linux内核中的实现通常是通过 sys_clone 系统调用来完成的,sys_clone 是创建新进程的底层系统调用,该过程分析如下:

1.首先是fork触发系统调用sys_clone,然后最终执行的是do_fork。
2.fork创建了两个进程,一个父进程,一个子进程,其中子进程是对父进程的拷贝,它从父进程处复制了整个进程的地址空间,只有进程号和一些计时器等等是自己独有的,由于要复制很多资源,所以fork创建进程是很慢的。
3.fork执行一次有两次返回值,在父进程里返回新建的子进程编号,在子进程里返回0.由于创建进程的三种方式最终都是调用do_fork。
4.创建子进程的一个重要的过程是复制父进程里面的资源,有看到下面的copy_process函数,所以基本判断是复制资源的函数.这段代码是创建子进程的精华部分,所有的创建进程上下文,为新进程设置新的pid,还有复制代码,都在这一部分了。

3、使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证对Linux系统创建一个新进程的理解
1)打开shell并启动menuOS
在这里插入图片描述
代码如下

cd LinuxKernel
rm -rf menu
git clone https://github.com/mengning/menu.git
cd menu
mv test_fork.c test.c
make rootfs

测试fork功能
在这里插入图片描述
2)在shell中启动内核,打开调试模式
在这里插入图片描述
3)设置断点
在shell2中使用gdb调试,在sys_clone、do_fork、dup_task_struct、copy_process、copy_thread、ret_from_fork处设置断点,命令如下:

cd LinuxKernel
gdb
file linux-3.18.6/vmlinux
target remote:1234
b sys_clone
b do_fork
b dup_task_struct
b copy_process
b copy_thread
b ret_from_fork

在这里插入图片描述
在这里插入图片描述
在gdb中continue执行到断点do_fork处:
在这里插入图片描述
copy_processcopy_thread断点
在这里插入图片描述

二、实验总结

  • 对“Linux 系统创建一个新进程”的理解

在Linux系统中,创建新进程的过程是通过 fork
系统调用完成的。fork系统调用从内核返回两次:一次回到父进程,另一次回到新产生的子进程。它实际上是由clone()系统调用实现的。子进程和父进程最大的区别就是在于他们拥有不同的PID。

  • 分析新进程的执行起点及对应的堆栈状态

创建的新进程的执行起点:ret_from_fork
在Linux中,新进程的堆栈状态如下:
*childregs = *current_pt_regs(); //复制内核堆栈
childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!
p->thread.sp = (unsigned long) childregs;//调度到子进程时的内核栈顶
p->thread.ip = (unsigned long) ret_from_fork;//调度到子进程时的第一条指令地址 ip指向的是ret_from_fork,所以是从这里开始执行的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

20232806安星宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值