Linux内核进程管理

7 篇文章 0 订阅

Linux进程状态
TASK_ RUNNING– 进程是可执行的。它或者正在执行,或者在等待队列中等待被执行。(相当于 就绪态+运行态)
TASK_ INTERRUPTIBALE(可中断)–进程正在睡眠/阻塞,等待某些条件的达成。也可能因为接收到信号而提前被唤醒(浅睡眠)。
TASK_ UNINTERRUPTIBALE(不可被中断)–与可中断状态相同,但即使接收到信号也不会被唤醒(深睡眠)
___TASK_ TRACED--被其他进程跟踪的进程。
_TASK_ STOPPED(停止)- -进程停止执行。进程没有投入运行,也不能投入运行。
Linux进程状态转换图
请添加图片描述
Linux进程PCB
task_ struct 数据结构剖析
在linux中每一个进程都由task_ struct 数据结构来定义.
task_ struct就是 我们通常所说的PCB.它是对进程控制的唯一手段也是最有效的手段.当我们调用fork()时,系统会为我们产生一个task_ struct结构。 然后从父进程那里继承一-些数据,并把新的进程插入到进程树中,以待进行进程管理。因此了解task_ struct的结 构是我们理解任务调度的关键。
task_ struct
请添加图片描述
task_ struct剖析( 1)
请添加图片描述
task struct剖析( 2 )
进程标识符
pid_ t pid
pid_ t tgid
系统调用getpid()返回什么
Linux系统允许用户使用一个叫做进程标识符的PID来标识进程,PID顺序编号,新创建进程是前一个进程的PID加1,不过PID值有一个上限,达到上限之后再开始循环使用闲置的小PID。
task_ struct剖析 (3)
进程内核栈

void *stack;

当进程通过系统调用陷入内核时,内核代码所使用的栈并不是用户空间中的栈,而是一个内核空间的栈,也就是进程内核栈,它用于支持系统调用中的函数调用和局部变量,还用于保存一些系统调用前的应用信息,如用户空间栈指针、系统调用参数。
task struct剖析 (4)
迸程标志

unsigned int flags;

请添加图片描述
task_ struct剖析 (5)
进程亲属关系
请添加图片描述
说明:
parent和real_ parent一般情况下是同一个进程,只有当进程被跟踪时,parent会去指向跟踪进程。.
task_ struct剖析 (6)
请添加图片描述
Linux内核PCB组织形式
(1)thread_ info
请添加图片描述
请添加图片描述
(2)thread_ union
请添加图片描述
thread_ info 与 stack
请添加图片描述
thread_ info 与stack紧密结合的好处:
①方便快速定位到task_ struct

(1)thread_ union占 据两个连续的页框,并且让第一个页框的起始地址是2的13次方的整数倍。
(2)esp寄存器中存放的当前栈指针。
(3)屏蔽掉esp的后13位,就可以得到thread_ info结 构的地址

由下列指令完成:
请添加图片描述
请添加图片描述
这样获得的是thread_ info的基地址,由于task字段在thread_ info结构中的偏移量是0,因此,p就指向了当前进程的task_ struct。
这就是内核中经常要用的current宏的实现。注: current宏永远指向系统当前运行的进程。

②在多处理器系统上,每个硬件处理器通过检查栈就可以获得当前正确的进程。早期Linux版本中,引入全局变量current来标识当前正在运行的进程描述符,在多处理器系统中,有必要把current定义为一个数组,每个元素对应一个可用的CPU。

Linux内核线程
(1)Linux实现线程的机制非常独特,从内核的角度来说,并没有线程的概念
(2)Linux把所有的线程都当做进程来实现,内核并没有准备特别的调度算法专门为线程服务,线程和进程使用同样的结构体
(3)task_ struct, 所以在内核看来,线程看起来像是一个普通的进程,只不过线程和其他一些进程共享某些资源,比如:地址空间。
Linux进程和线程
Linux不区分进程和线程,统称为任务(task)。
Linux应用层创建进程接口–fork()
Linux应用层创建线程接口–pthread_ create()
三个系统调用如何调用do_ fork
请添加图片描述
Linux进程和线程
请添加图片描述
请添加图片描述
创建参数
请添加图片描述
do_ fork()
请添加图片描述
请添加图片描述
请添加图片描述
Linux中三个特殊的进程
内核三个特殊进程

IDLE进程: PID=0
init进程: PID=1
kthread进程: PID=2

内核创建三个进程的顺序是,先创建0号,由0号创建了1、2号其中IDLE进程是静态创建的,内核中唯一个不是由kernel_ thread创建的进程。
1号init进程,是所有用户态进程的父进程。
2号kthread进程,是所有内核线程的父进程。
Linux内核线程的创建
(1)内核经常要在后台进行一些操作,这种任务可以通过内核线程完成。
(2)内核线程和普通线程的区别在于,它们只运行在内核空间,从来不会切换到用户空间去。
Linux创建内核线程的过程
内核线程的创建接口
请添加图片描述
threadfn:新线程运行函数
data:新线程传参
namefmt:新线程的命名.
新创建的线程默认处于不可运行状态,需要调用wake_ up_ process()明确地唤醒它。或者,你也可以直接调用kthread_ run()直接创建一个线程并让它运行起来,相当于kthread_ create()+wake_up process()的效果。
请添加图片描述
Linux内核线程的退出
内核线程启动后就一直运行直到调用do_ exit()退出,或者内核的其他部分调用kthread_ stop()终止它。
请添加图片描述
kthread_ create实现
请添加图片描述
请添加图片描述
请添加图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值