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


    进程的描述和进程的创建

    进程的描述

    1、操作系统内核实现操作系统的三大管理功能:

    • 进程管理

    • 内存管理

    • 文件系统

    其中最核心的功能是进程管理。

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

    3、对进程状态的描述:

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

    • 在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()唤醒。

    进程的创建

    1、0号进程的初始化:
    init_task为第一个进程(0号进程)的进程描述符结构体变量,它的初始化是通过硬编码方式固定下来的,除此之外的其它进程的初始化都是通过do_fork复制父进程的方式初始化的。

    2、fork、vfork、clone这3个系统调用和kernel_thread内核函数都可以创建一个新进程,而且都是通过do_fork函数来创建进程的,只不过传递的参数不同。

    3、进程的创建过程:

    利用fork()系统调用来创建新进程,把当前进程的描述符等相关进程资源复制一份,从而产生一个子进程,并根据子进程的需要对复制的进程描述符做一些修改,然后把创建好的子进程放入运行队列。在进程调度时,新创建的子进程处于就绪状态有机会被调度执行。

    4、进程创建过程中的重要函数或数据结构:

    • do_fork():主要完成调用copy_process()复制父进程信息、获得pid、调用wake_up_new_task将子进程加入调度器队列等待获得分配CPU资源运行、通过clone_flags标志做一些辅助工作。
    • copy_process():主要完成调用dup_task_struct复制当前进程(父进程)描述符task_struct、信息检查、初始化、把进程状态设置为TASK_RUNNING(就绪态)、采用写时复制技术逐一复制所有其他进程资源、调用copy_thread初始化子进程内核栈、设置子进程pid等。
    • dup_task_struct():复制当前进程(父进程)描述符task_struct和copy_thread初始化子进程内核栈。
    • thread_info:小型的进程描述符,占据连续的两个页框,通过task指针指向进程描述符。内核栈有高地址到低地址增长,thread_info结构有低地址到高地址增长。
    • copy_thread():完成内核栈关键信息的初始化。如果创建的是内核线程,则子进程开始执行的起点是ret_from_kernel_thread;如果创建的是用户态进程,则子进程开始执行的起点是ret_from_fork。

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

    1、增加fork系统调用

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

    2、启动内核

    3、gdb跟踪

    启动gdb,将内核加载进来,建立连接,并在sys_clone、do_fork、dup_task_struct、copy_process、copy_thread、ret_from_fork处各设置断点。

    总结

    进程的创建过程大致是复制进程描述符、一一复制其它进程资源(采用写时复制技术)、分配子进程的内核堆栈并对内核堆栈关键信息进行初始化。
    问题是fork、vfork、clone这三种系统调用的不同,通过查阅资料发现:

    • fork():子进程拷贝父进程的数据段,代码段,父子进程的执行次序不确定;
    • vfork():创建的子进程与父进程共享数据段,而且子进程将先于父进程运行;
    • clone():是则可以将父进程资源有选择地复制给子进程,而没有复制的数据结构则通过指针的复制让子进程共享。
  • 相关阅读:
    阅读《最后期限》有感(1)
    软件工程课程改进建议
    团队开发第二次冲刺第七天
    返回一个二维整数数组中最大联通子数组的和
    大道至简阅读笔记三
    大道至简阅读笔记二
    大道至简阅读笔记一
    团队冲刺阶段二第十次站立会议
    对软工课程的意见建议
    团队冲刺阶段二第九次站立会议
  • 原文地址:https://www.cnblogs.com/Huyiming/p/11779115.html
Copyright © 2020-2023  润新知