Linux内核--进程管理

1、进程生命周期

    某个进程通过系统调用fork,创建一个用于执行程序的进程。生成此进程的进程称为父进程,被生成的进程称为子进程。子进程通过复制父进程的数据得以创建;

    父进程执行系统调用wait,等待子进程结束;

    子进程通过系统调用exec将程序读取到内存并开始执行;

    当程序执行完毕后,子进程通过系统调用exit结束自身的运行并进入僵尸状态;

    父进程得到子进程的执行结果后清理子进程。

2、创建进程

    进程的复制:通过将父进程的数据复制到子进程,以此创建新的进程,被复制的数据有:proc[]数组元素、复制数据段

    系统调用fork:用户程序在执行fork时会首先调用C语言的库函数fork(),在此库函数中再执行sys fork来访问系统调用fork()

    子进程的处理:在内核的fork() 处理中,子进程从newproc()返回处开始执行;newproc()是实际创建进程的函数,他负责将proc[]中代表执行进程的元素和执行进程的数据段复制到子进程中,代码段不属于复制对象,子进程和执行进程共享相同的代码段

3、切换执行进程

    中断执行进程:执行进程在执行内核函数sleep() 后进入休眠并中断当前处理,此后,由于swtch()被调用,执行进程发生切换

    内核函数sleep()一般在下述情况下被调用:用户程序访问了系统调用wait、等待周边设备处理完毕、等待使用中的资源被释放

    选择执行进程的算法:swtch()用来选择下一个将被执行的进程。他从起始位置遍历proc[],并将满足下列条件的进程选择为执行进程

        处于可执行状态(SRUN)

        拥有最高的执行优先级(proc.p_pri的值最小)

    setpri()函数用来随时调整各进程的执行优先级

    上下文切换:执行进程被中断时,将当前执行状态保存于user结构体中。当被中断的进程再次执行时,通过user结构体恢复以前的执行状态,这个处理被称作上下文切换

    系统调用wait:wait具有以下两个功能:终端当前进程等待子进程执行结束,以及清理执行结束的子进程

    sleep() :sleep()接受两个参数:chan和pri。chan为任意变量的地址,其值将被赋给执行进程的proc.p_wchan。wchan代表waiting channel,表示此进程正在等待proc.p_wchan所指向的资源

    wakeup()将进程从休眠状态唤醒至可执行状态;系统利用sleep()和wakeup()实现多个进程等待同一资源时的同步处理;

    setrun()将由参数指定的进程设定为可执行状态

4、执行程序:执行程序时,首先需要将该程序的执行文件从块设备读取到内存,并将其配置到执行进程的虚拟地址空间;

    系统调用exec用于执行程序执行文件的读入处理和分配内存的处理,它不会改变已打开文件和当前目录的数据。父进程的数据按原状保留。

    执行文件的格式:程序执行文件从文件头开始依次由下述部分构成:文件头、代码、数据、符号表、重定位比特

    系统调用exec:用户程序调用exec后将执行下述处理:

  • 将传递给执行程序的参数存入缓冲区
  • 将程序从块设备读取到内存
  • 更新进程的虚拟地址空间
  • 将存入缓冲区的参数压入栈
  • 对SUID、SGID进行处理
  • 对寄存器和信号进行初始化 

5、进程的终止

    系统调用exit的主要功能如下所示:

  • 关闭打开的文件
  • 将当前目录的参照计数器减1
  • 释放代码段
  • 将user结构体复制到交换空间
  • 释放数据段
  • 使进程进入僵尸状态
  • 唤醒父进程或init进程
  • 如果当前进程存在子进程,则将其设置为init进程的子进程

    在进程的最后阶段执行swtch()切换执行进程

6、数据区域的扩展

    系统调用break用来扩展或缩小数据段中数据区域的长度,供用户程序调用的C语言库函数malloc()等使用break实现对堆区域的扩展等操作

7、管理内存和交换空间

    map结构体:内核利用map结构体对物理内存和交换空间的未使用区域进行管理

    coremap[]用来管理物理内存,swapmap[]用来管理交换空间

    mfree()用来释放物理内存和交换空间

猜你喜欢

转载自blog.csdn.net/m0_38099899/article/details/80791733