2023-2024-1 20232827 田紫晴《Linux内核原理与分析》第七周作业

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

一、实验要求

  • 阅读理解 task_struct 数据结构 https://github.com/torvalds/linux/blob/v3.18-rc6/include/linux/sched.h#L1235
  • 分析 fork 函数对应的内核处理过程 sys_clone,理解创建一个新进程如何创建和修改 task_struct 数据结构;
  • 使用 gdb 跟踪分析一个 fork 系统调用内核处理函数 sys_clone ,验证您对 Linux 系统创建一个新进程的理解,推荐在实验楼 Linux 虚拟机环境下完成实验。 特别关注新进程是从哪里开始执行的?为什么从那里能顺利执行下去?即执行起点与内核堆栈如何保证一致。
  • 根据本周所学知识分析 fork 函数对应的系统调用处理过程,撰写一篇署名博客

二、实验过程:

1.阅读理解 task_struct 数据结构 

task_struct 是 Linux 内核中表示进程或任务的关键数据结构之一。它包含了关于进程状态、调度信息、资源占用等方面的信息。task_struct 数据结构定义了进程在系统中的各种属性和状态,使得内核能够管理和调度这些进程。task_struct 数据结构在 Linux 内核中扮演着重要的角色,它使得内核能够有效地管理和调度系统中的各个进程。

2.分析 fork 函数对应的内核处理过程 sys_clone,理解创建一个新进程如何创建和修改 task_struct 数据结构

`fork` 函数在 Linux 内核中对应的系统调用是 `sys_clone`,其内核处理过程涉及到创建新进程并修改 `task_struct` 数据结构。

1. **创建新进程**:`sys_clone` 首先通过 `do_fork` 函数创建一个新的进程。在这个过程中,它会复制父进程的 `task_struct` 数据结构,得到一个新的 `task_struct` 用于新进程。这个过程确保新进程继承了父进程的大部分属性和状态。

2. **设置新进程的状态和标识符**:在 `do_fork` 中,新进程的状态被设置为可执行(`TASK_RUNNING`),同时分配一个新的进程标识符(`pid`)。这确保新进程可以被调度和唯一标识。

3. **共享地址空间**:新进程的地址空间结构 (`mm`) 会指向与父进程相同的地址空间,即共享代码、数据和堆栈。这是通过调用 `copy_mm` 等函数来实现的。

4. **复制文件系统信息**:新进程的文件系统信息 (`fs`) 通常也会与父进程共享,以保持一致性。这是通过调用 `copy_fs` 等函数来实现的。

5. **信号处理的复制**:新进程会复制父进程的信号处理信息,确保新进程在创建时拥有相同的信号处理状态。

总体而言,`sys_clone` 系统调用通过调用 `do_fork` 实现新进程的创建,而 `do_fork` 则负责复制父进程的 `task_struct` 数据结构以及相关信息,确保新进程能够正确继承和共享父进程的状态。这样,新进程就能在一个新的环境中运行,而父进程和子进程之间的关系也得到了适当的设置。

3.gdb 跟踪分析 

打开实验楼shell,输入图中命令,删除原来的menu,并clone新的menu,用test_fork.c覆盖test.c,重新执行make rootfs:

 

调试menuOS。重开一个shell,输入cd LinuexKernel,进入目录;再输入gdb进入分布调试:

 输入命令,设置断点sys_clone。执行fork命令,停在了断点sys_clone处:

执行n,经过几行代码直到p = dup_task_struct(current);停在断点copy_process处,

 程序执行到断点copy_thread后,执行n,如下

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

4.分析 fork 函数对应的系统调用处理过程 

`fork` 函数对应的系统调用在 Linux 内核中是 `sys_fork`。这个系统调用的处理过程涉及到创建一个新的进程,通过复制父进程的状态和代码来生成子进程。以下是 `fork` 系统调用的主要处理过程:

1. **准备系统调用参数**:用户空间通过系统调用 `fork` 提交请求给内核,参数传递通常通过寄存器或栈完成。主要参数是一个指向 `struct pt_regs` 结构的指针,其中包含了系统调用的参数。

2. **创建新的进程描述符(task_struct)**:内核通过调用 `do_fork` 函数创建一个新的进程。在这个过程中,新的进程描述符(`task_struct`)会被复制,并初始化一些基本的属性。新进程被标记为就绪(`TASK_RUNNING`)状态。

3. **设置新进程的地址空间**:新进程的地址空间结构 (`mm`) 会被复制,但是采用了写时复制(Copy-On-Write)的机制。这意味着只有在进程尝试写入某个页面时,才会创建一个新的页面副本。

4. **为新进程分配唯一的进程标识符(PID)**:内核为新进程分配一个新的唯一标识符(PID),并将其返回给用户空间。

5. **复制文件系统信息**:新进程的文件系统信息 (`fs`) 通常也会与父进程共享,以保持一致性。这是通过调用 `copy_fs` 等函数来实现的。

6. **复制信号处理**:新进程会复制父进程的信号处理信息,确保新进程在创建时拥有相同的信号处理状态。

7. **返回值**:对于父进程,`fork` 系统调用返回子进程的 PID;对于子进程,返回值是 0。这样,用户空间程序可以根据返回值来确定当前是在父进程还是子进程中执行。

总的来说,`fork` 系统调用的处理过程涉及到复制父进程的状态,为新进程分配资源,并返回合适的信息给用户空间。这样,父进程和子进程就能够在各自的环境中继续执行。

三、实验总结

       通过分析 task_struct 数据结构、sys_clone 函数的内核处理过程以及使用 GDB 跟踪分析,我更深入地理解 Linux 内核是如何创建新进程的。这包括如何复制父进程的状态,为新进程分配资源,以及新进程从何处开始执行,这些过程确保了进程间的正确切换和独立性。 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值