在运行队列就是运行状态:
不要用人的感觉去评价CPU的速度,而且CPU是轮转调度
其中,阻塞状态就像是这样:
此时这个进程就处于了阻塞状态
当我从键盘输入数据之后
才能继续向下运行
这是Linux内核源代码对于进程状态的描述
static const char * const task_state_array[] = {
"R (running)",
"S (sleeping)",
"D (disk sleep)",
"T (stopped)",
"t (tracing stop)",
"X (dead)",
"Z (zombie)",
};
其中:
R:运行状态
阻塞状态有以下4种:
S:睡眠状态:
D:睡眠状态:
T:暂停状态:
t: 暂停状态:
还有两个状态:
Z:僵尸状态
X:退出状态
下面我们就在Linux环境下
来看一下各种状态的样子
我们先来看一下R状态:
这里我们写了一个while(1)死循环的代码来看R状态
当我们退出mycmd对应的进程之前
这个进程显示R+状态
什么叫做睡眠状态呢?
睡眠状态属于阻塞状态的一种
是比较常见的一种阻塞状态
该进程因为需要等待某种软硬件资源的提供而进入睡眠状态
就跟我们刚才说的教材上对于进程状态的描述是一样的
为什么说S是可终止睡眠呢?
因为这种睡眠状态是可以被我们使用ctrl+c退出的
下面给大家看一下:
sleep(1)是让程序休眠1s
在这段期间进程处于睡眠状态,一直等待这1s过去
这个进程一直处于S状态,当我们ctrl+c时,该进程正常退出
你说的好像没什么用吧,一般情况下还能退出不了吗?
有些时候还真就退出不了
前面给大家看一看
先介绍两个概念
前台进程: 进程状态显示为+,可以被ctrl+c退出掉
此时是无法执行指令的
后台进程:进程状态显示时没有+,无法被ctrl+c退出掉
此时是可以执行指令的
我们正常./可执行程序名字
的时候是默认以前台进程方式来运行的
但是./可执行程序名字 &
就会以后台进程方式来运行该进程
./mycmd 前台进程
./mycmd & 后台进程
这是作为前台进程运行:
此时我输入了ls,pwd这些指令,都没有用
而且ctrl+c成功退出
此时我输入ls,pwd这些命令就都有用了
不过ctrl+c无法退出
只能使用kill -9 进程PID来杀死进程才能退出
关于前台进程和后台进程我们以后还会详细介绍的
目前在这篇博客中大家先了解一下即可
有些细心的小伙伴可能发现了一个现象:
刚才我们printf打印的那个进程为什么明明打印了
却还是显示S状态呢?
它不应该显示R状态吗?
因为:
printf的实质是在显示器上打印
printf导致该进程频繁与显示器交互,交互时因为要等待显示器所以就处于S了
而且大部分时间是处于交互的
因此大部分时候我们看到的都是S,
只有非常低的概率才能看到R
也正是因为这个原因,我们在一开始介绍R状态的时候才会只用一个while(1)死循环
首先要说明一点:
操作系统在被逼急了的时候(资源特别紧张的时候),是会杀掉进程的(至少Linux下是这样)
因此当我们的计算机资源特别特别紧缺的时候,操作系统可能就会杀掉一部分进程
这时,如果一个特别重要的进程被杀掉了,那么会对用户造成非常大的影响.因此才有了这个D状态的出现
T:暂停状态
为什么会有暂停状态呢?
有些时候某些进程具有危险操作,如果你非要执行这些进程,那么操作系统就会暂停这个进程来保护计算机
首先我们要先介绍几个命令
kill -l:查看进程信号
kill -19 进程PID:暂停进程
kill -18 进程PID:让暂停进程继续运行
一旦暂停进程了,那么这个进程就会自动从前台进程切换为后台进程,即使之后又继续运行了,但是依然是后台进程
为什么会有t状态呢?
"t (tracing stop)"
追踪停止
其实在我们使用gdb调试程序的时候,这个进程就处于t状态
大家一定不要忘了,想要用gdb调试可执行程序
使用gcc编译时要加-g选项,即使用debug模式生成可执行程序
Z是僵尸状态,
处于僵尸状态的进程就是僵尸进程
我们下面会详细解释的
死亡状态(退出状态)
当一个进程要退出的时候,先把它置为X状态,然后退出这个进程
这个代码的含义就是:
创建一个子进程,然后子进程运行5秒之后就会退出
父进程一直运行,但是父进程并不会接收子进程的结束信息
我们知道
Linux中的普通进程都有它的父进程
除非该进程是由我们所创建的进程所创建的
否则该进程的父亲就是bash
而bash会自动接收它的子进程的退出信息
那么能不能让父进程接收子进程的退出信息呢?
当然可以啦
使用
wait(NULL);
等待子进程 会接收子进程的退出信息
头文件:
#include
这个代码的意思是:
子进程运行5s后退出
父进程运行8s后退出,退出后立即接收子进程的退出信息
然后休眠5s后退出
在子进程退出之后,父进程接收子进程退出信息之前
子进程一直处于僵尸状态
父进程接收子进程退出信息之后
子进程成功退出
这个代码的意思是:
子进程一直死循环运行
父进程运行5s之后退出
退出之后子进程就成为了孤儿进程
在Linux中
优先级是通过一个整形变量来表示的
默认优先级是80
整个优先级的区间是[60,99](包括60 和99)
一共40个整数
数字越低,优先级越高
数字越高,优先级越低
Linux系统允许用户调整优先级,但是不允许用户直接修改优先级
而是通过修改nice值的方式来修改优先级
ps -l 查看进程信息
注意:我们不建议去调整优先级
在这里介绍这个修改进程优先级的方法是为了让我们
以后如果别人修改进程优先级,我们能看懂
还有一点就是加深一下理解
top命令 修改进程优先级
按q键退出
新PRI=PRI(old)+nice
注意:
1.PRI(old)一直都默认是80
这样规定是为了让我们以后修改进程优先级的时候可以不用管上一次的优先级是多少
修改起来更加方便
2.因为PRI的范围是[60,99]
而PRI(old)一直都是80
所以nice的范围是[-20,19]
1.ps -la 查看进程信息
2.top
进入top之后,我们按r
然后输入我们想要修改的进程的PID
然后输入nice值
最后退出即可
任何的分时操作系统,在进程调度上需要进行较为公平的调度!
下面我们来测试一下进程优先级的上下限
分别调整两次mycmd这个进程的优先级
第一次调为0(输入-80)
第二次调为200(输入120)
直接不允许我调整为0
我想要调整为200,结果只能调整为99
首先我们先举一个日常生活中的小例子
其实进程切换也是这样进行的
进程切换是这样运行的:
那么Linux操作系统的调度特性是如何做到的呢?
这就跟Linux运行队列的结构紧密相关了
下面我们就来看一下Linux运行队列的结构
乍一看这个结构好麻烦啊
不要担心,我们只需要关心几个重要的结构数据即可
下面我们会一一介绍这个运行队列的结构是如何同时兼顾
优先级,效率和饥饿问题的
操作系统是根据nr_active的值来迅速确定queue数组中的进程个数的
据此判断什么时候可以交换active指针和expired指针的指向
当一个进程的时间片耗尽了,这个进程就是过期了,就会进入过期队列当中
当一个进程运行结束了,那么就退出运行队列,也不再进入过期队列 而是变为僵尸进程,等待父进程读取结束信息
可是这样的话,每次都还要去遍历一遍这个queue数组
又因为你CPU进程切换非常频繁,效率能不能再好一点了
这就是那个int bitmap[5];的作用了
以上就是Linux进程状态(僵尸进程,孤儿进程)+进程优先级+进程调度与切换的全部内容,希望能对大家有所帮助!