Linux进程管理与调度

Linux下的进程管理


进程与线程概念

进程:可执行代码、数据、地址空间、信号,打开的文件


进程描述符与task_struct循环队列

描述进程的数据结构task_struct和thread_info

task_struct可以表征一个进程,称其为进程描述符,内核中用它来组成循环队列实现进程的调度与管理


task_struct的分配、存储与查找

task_struct由slab分配,一般通过一个指针来存储task_struct的地址,不同架构的CPU处理方式不同,PPC结构用一个寄存器来存储,X86存储在thread_info结构中,所以task_struct的查找也与体系结构有关


进程状态与状态修改

状态

TASK_RUNNING(正在运行、就绪可以运行)

TASK_INTERRUPTIBLE

TASK_UNINTERRUPTIBLE

TASK_ZOMBLE

TASK_STOPPED

设置状态

set_task_state(task, state)’

进程状态机与状态切换


进程间的关系(进程家族树)

由task_struct维护

task_struct task_struct

{

.......

task_struct *parent;//父进程

list * child_list;//子进程列表

......

}


进程创建与写时拷贝(fork)

进程创建过程

fork()

创建内核栈、thread_info、task_struct,此时这三个数据结构和父进程完全相同

        通过修改task_struct以区分父进程

        设置标志保证子进程处于非运行态

        get_pid()得到有效PID

        与父进程共享剩余时间片

        do_fork()返回子进程的指针

如果do_fork()成功返回,子进程被唤醒执行

进程与子进程的区别(PID/PPID/资源统计量)

写时拷贝fork()

新创建的进程和父进程共享资源,都以只读方式访问,只有在需要写入的时候才会copy,这样会避免资源占用

具体通过clone系统调用实现

Linux线程的实现

线程与进程

Linux的线程进而进程差不多,进程和线程最终创建都是通过clone()系统调用实现的,区别只是创建进程和线程时给clone传递的标志不同

内核线程的创建

进程退出do_exit()

do_exit()完成以下任务

设置task_struct的标志变量为PF_EXTTING

删除del_time/exit_mm/exit_sem、files/fs的引用计数

exit_notify通知父进程同时将自己设置成TASK_ZOMBLE

调用shedule()切换到其他进程执行

do_exit完成后,线程所占用的资源大多被释放,但仍然占有内核栈、thread_info和task_struct


进程描述符task_struct的删除

wait函数

挂起调用wait的进程,知道有一个子进程退出,退出时候返回子进程的PID

release_task函数

进程退出时,保留task_struct的原因:在进程退出后仍然可以让父进程获取他的信息,所以进程的终结是的清理工作和和删除进程描述符分开进行,task_struct删除具体步骤

减少进程用户的的进程数

回收PID

删除进程

在ptrace上删除对该进程的跟踪

删除内核栈和thread_info所占的的页,删除task_struct所占的slab高速缓存


孤儿进程

产生

父进程在子进程结束之前退出,造成子进程的资源没人回收,一直处于TASK_ZOMBLE状态,占用资源

Linux解决措施

为兄弟进程重新寻找父进程,找不到则以init进程昨晚所有兄弟进程的父进程,父进程调用wait函数回收资源,清楚TASK_ZOMNLE进程


Linux进程调度

调度概念

从一组就绪态(TASK_RUNNING)的进程中根据某种算法选择一个,并计算出执行时间让其执行,就是调度程序的任务

抢占式OS与非抢占式OS

抢占式:进程用完时间片之后,让出资源,调度程序调度另一个任务执行,该过程称之为抢占,相当于另一个任务抢占了当前任务的执行,当前多数OS都是抢占式OS

非抢占式:除非进程自己主动让出资源,否则进程将一直执行下去直到结束,造成的影响是一个任务占用资源时间过长,导致其他任务无法执行,最糟糕的情况是一个绝不让步的悬挂进程可能造成整个系统的崩溃

猜你喜欢

转载自blog.csdn.net/zhanghao864442969/article/details/72674760