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



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

1、阅读理解 task_struct 数据结构
2、分析 fork 函数对应的内核处理过程 sys_clone,理解创建一个新进程如何创建和修改 task_struct 数据结构
3、使用 gdb 跟踪分析一个 fork 系统调用内核处理函数 sys_clone ,验证自己对 Linux 系统创建一个新进程的理解, 特别关注新进程是从哪里开始执行的?为什么从那里能顺利执行下去?即执行起点与内核堆栈如何保证一致。
4、根据本周所学知识分析 fork 函数对应的系统调用处理过程


二、实验过程

1.阅读理解 task_struct 数据结构

task_struct 数据结构是 Linux 内核中用于表示进程或线程的核心数据结构。它包含了大量的字段,用于管理和维护进程的各个方面。其中一些关键字段包括进程状态、内核堆栈、引用计数、进程标志、调试标志、唤醒信息、CPU信息等。task_struct 中的信息用于实现进程调度、资源管理、进程间通信、调试和跟踪等功能。task_struct设计复杂,是Linux 内核对进程管理的高度精细控制,确保操作系统能够有效地管理多个进程的执行,提供了强大的多任务处理能力。

以下是借助ChatGPT进行进一步分析如下:
在这里插入图片描述

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

fork 是一个创建新进程的系统调用,它以当前进程(父进程)为模板,创建一个几乎完全相同的新进程(子进程)。新进程是父进程的副本,但两者在执行上下文和资源方面是独立的。这种能力是实现多任务处理的基础,允许一个进程创建并控制其他进程。fork 系统调用对应的内核处理过程实际上是通过 sys_clone 来实现的。

① fork系统调用(fork.c):
当用户进程调用 fork 时,它实际上是在用户空间发出了一个系统调用请求,请求内核创建一个新进程。fork 函数的工作步骤如下:

1、父进程通过fork调用陷入到内核(系统调用中断),内核创建一个新的 task_struct 结构体,作为子进程的描述。
2、内核为子进程分配一个独立的进程ID(PID)。
3、内核复制父进程的内存布局到子进程,包括代码段、数据段、栈等。
4、内核复制父进程打开文件描述符表,以便子进程能够访问相同的文件。 内核创建子进程的内核堆栈。
5、最后,内核将子进程标记为可执行,并设置返回值0(在父进程中)或子进程的PID(在子进程中)。 此后,fork 函数返回两次,一次对于父进程,一次对于子进程。

在C库中,fork 函数被调用时,实际上是使用 syscall 指令来触发系统调用,这将调用 do_fork 函数。以下是 do_fork 函数的关键代码:

asmlinkage long do_fork(unsigned long clone_flags, unsigned long stack_start,
                        struct pt_regs *regs, unsigned long stack_size,
                        int __user *parent_tid, int __user *child_tid) {
    struct task_struct *p;
    struct pid *pid;
    int trace = 0;
    struct task_struct *tracee;
    struct pid *tracee_pid;

    // 创建新的 task_struct 数据结构
    p = dup_task_struct(current);
    if (!p)
        return -ENOMEM;

    // 复制或共享父进程的内存布局(代码、数据、栈等)

    // 复制或共享其他资源(例如文件描述符、信号处理程序等)

    // 初始化新进程的状态等字段
    p->state = TASK_RUNNING;
    p->pid = alloc_pid(p);

    // 将新进程添加到调度队列

    // ...

    return p->pid;
}

② sys_clone(kernel/fork.c):
内核处理 fork 系统调用时实际上调用了 sys_clone 函数,因为fork 实际上是 sys_clone 系统调用的一种特殊形式,它传递了一组标志位和参数。以下创建进程内核部分的关键步骤如下:

1、sys_clone 检查父进程的权限和参数是否有效,并为新进程分配一个唯一的PID。
2、设置新进程的状态、进程组等属性。
3、调用copy_process 函数,它复制了父进程的 task_struct结构和其他进程数据。这包括复制虚拟地址空间,文件描述符,信号处理程序等。
4、copy_process return后,内核为新进程安排调度并在需要时分配CPU。

以下是 sys_clone 的代码,能体现出sys_clone与 do_fork 函数之间的关系

asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
                          int __user *parent_tid, int __user *child_tid,
                          unsigned long tls) {
    // 获取当前进程的寄存器上下文
    struct pt_regs *regs = current_pt_regs();
    
    // 调用内核的 do_fork 函数来创建新进程
    return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
}

③ 如何创建新进程和修改 task_struct 数据结构
如何创建新进程和修改 task_struct 数据结构在①②中其实已经涉及,这里补充ChatGPT的理解:
在这里插入图片描述

3.gdb 跟踪分析

1、与以前几次实验一样,先重新编译新内核的menu,再将test_fork.c覆盖在运行程序test.c上

cd ~/LinuxKernel
rm menu -rf
git clone https://github.com/mengning/menu.git
cd menu 
mv test_fork.c test.c//在MenuOS中增加fork命令,并覆盖掉test.c文件
make rootfs  
MenuOS>>help  

在这里插入图片描述
2、使用gdb对fork()函数进行跟踪分析
与之前几次实验一样,首先进入一个冻结内核,然后打开一个空shell,再进行gdb调试:

进入冻结内核:

cd LinuxKernel   
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S  //冻结内核的启动

新打开一个空shell,进入gdb调试,并建立连接:

cd LinuxKernel 
gdb
(gdb)file linux-3.18.6/vmlinux
(gdb)target remote:1234

在这里插入图片描述
冻结的内核开始运行后,输入fork可发现fork输出了父进程和子进程,说明fork调用成功。
在这里插入图片描述

3、下面进入fork的调试:
分别对系统调用sys_clone、do_fork、dup_task_struct、copy_process、copy_thread、ret_from_fork设置断点进行单步调试
在这里插入图片描述
在这里插入图片描述

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

fork 函数在Linux内核中用于创建新进程,它实际上是一个系统调用,用于复制当前父进程的状态来创建一个新进程,这个新进程就是子进程。该函数的系统调用过程过程包含多个内核函数,主要是do_fork函数,它负责完成子进程的创建和初始化,并调用copy_process函数,用于复制父进程的关键数据结构,包括文件描述符表、内存映射、信号处理程序等。copy_thread函数也比较重要,它可以复制内核堆栈的内容,以确保新进程拥有独立的内核堆栈。


三、Chatgpt帮助

在这里插入图片描述
在这里插入图片描述


总结

通过本次实验,进一步了解了Linux 内核创建一个新进程的过程,即fork系统调用函数的运行过程,懂得了为什么会出现”一次调用,两次运行“的情况,从而对Linux内核有了新的理解。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值