2021-2022-1 20212808 《Linux内核原理与分析》第七周作业

本文详述了Linux内核中进程的描述,包括进程控制块struct task_struct,状态转换如TASK_RUNNING、TASK_ZOMBIE、TASK_INTERRUPTIBLE和TASK_UNINTERRUPTIBLE。分析了fork系统调用创建进程的过程,涉及do_fork、dup_task_struct和copy_thread等关键函数,并介绍了实验中使用gdb跟踪内核函数以理解新进程创建步骤,同时分享了实验中遇到的挑战和学习经验。
摘要由CSDN通过智能技术生成

进程的描述和进程的创建

1.进程的描述
  • 操作系统内核实现操作系统的三大管理功能:进程管理、内存管理、文件系统。

  • 在操作系统原理中,通过进程控制块PCB描述进程。在Linux内核中通过一个数据结构struct task_struct来描述进程,称其为进程描述符。

  • 在操作系统原理中,进程有就绪态、运行态和阻塞态3种基本状态。

  • Linux内核状态转换图:
    在这里插入图片描述

  • 在Linux内核中,当时用fork()系统调用来创建一个进程时,新进程的状态是TASK_RUNNING(就绪态但没有运行)。就绪态和运行态在Linux内核中都是TASK_RUNNING状态,此状态下进程是可运行的,也就是就绪态,是否在运行取决于它有没有获得CPU的控制权,即这个进程有没有在CPU中实际执行。如果在CPU中实际执行了,进程状态就是运行态;如果被内核调度出去了,在等待队列里就是就绪态。

  • 对于一个正在运行的进程,调用用户态库函数exit()会陷入内核执行该内核函数do_exit(),进程会进入TASK_ZOMBIE状态,即进程的终止状态。TASK_ZOMBIE状态的进程一般叫做僵尸进程,Linux内核会在适当的时候把僵尸进程处理掉,然后释放进程描述符。

  • 一个正在运行的进程在等待特定事件或资源时会进入阻塞态,阻塞态分为两种:
    TASK_INTERRUPTIBLE
    TASK_UNINTERRUPTIBLE。
    前者可以被信号和wake_up()唤醒,后者只能被wake_up()唤醒。

  • pid ,tgid用来标识进程。

  • 用数据结构struct task_struct 来描述进程
    SMP条件编译,on_rq运行队列。
    所有进程通过双向循环链表链起来。

  • 进程描述符的结构示意图
    在这里插入图片描述

  • 程序创建的进程具有父子关系。

  • fork系统调用在父进程和子进程各返回一次,没有打破条件分支的结构,可以在用户态创建一个子进程。
    在这里插入图片描述

2.进程的创建
  • 0号进程的初始化:
    init_task为第一个进程(0号进程)的进程描述符结构体变量,它的初始化是通过硬编码方式固定下来的,除此之外的其它进程的初始化都是通过do_fork复制父进程的方式初始化的。
  • sp用来保存进程上下文切换中的ESP寄存器状态,ip用来保存进程上下文中的EIP寄存器状态。
  • 进程的创建过程:
    利用fork()系统调用来创建新进程,把当前进程的描述符等相关进程资源复制一份,从而产生一个子进程,并根据子进程的需要对复制的进程描述符做一些修改,然后把创建好的子进程放入运行队列。在进程调度时,新创建的子进程处于就绪状态有机会被调度执行。
  • fork、vfork、clone这3个系统调用和kernel_thread内核函数都可以创建一个新进程,而且都是通过do_fork函数来创建进程的,只不过传递的参数不同。

实验六:分析 Linux 内核创建一个新进程的过程

  1. 进入LinuxKernel目录,删除menu目录,克隆一个新的menu
    在这里插入图片描述
  2. 进入menu目录,用make rootfs对新文件进行编译、自动生成根文件系统。新增了fork系统调用,在MenuOS输入help查询系统调用函数,测试新加入的fork命令。
    在这里插入图片描述
  3. 使用gdb跟踪系统调用内核函数,启动内核,可以看到它被冻结起来。
    在这里插入图片描述
  4. 水平分割启动gdb,输入命令进行连接
    在这里插入图片描述
  5. 在sys_clone、do_fork、dup_task_struct、copy_process、copy_thread、ret_from_fork处各设置断点。
    在这里插入图片描述
  6. 继续执行,分别停在sys_clone、do_fork,copy_process
    然后单步执行调试,会停留在第3个断点,停在dup_task_struct函数,进入dup_task_struct内部,将当前进程内核压栈压得那一部分寄存器复制到子进程中,以及赋值子进程的起点。
    继续执行调试,停留在copy_thread和ret_from_fork上
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值