当前位置: 首页 > article >正文

Linux系统编程:进程状态和进程优先级/nice

目录

一,相对于OS的进程状态

1.1运行状态

1.2阻塞状态

1.3挂起状态

二,并发执行与进程切换

2.1,CPU并发执行

2.2进程切换

三,Linux内核管理进程状态的方法

3.1查看进程状态

3.2R状态

3.3S状态

3.4D状态

3.5T状态

3.6X状态

3.7Z状态

3.8孤儿进程

 四,进程优先级

4.1优先级理解

4.2查看和调整优先级

4.3如何修改优先级

五,Linux内核调度算法 


一,相对于OS的进程状态

什么是相对于OS或者外设的进程状态呢?

就是进程的状态与外设建立联系的,后面我们会提到进程的R,S,T...状态,是为了与这个划分;

1.1运行状态

 进程是以运行队列的组织方式来通过调度器进行轮流调度的;调度器会将最前面的进程占用CPU;

占用CPU的进程就是正在运行的程序,而后面排队的是随时准备被调度的进程;这些处于运行队列的进程都处于运行态;

结论:并不是之后占用CPU正在执行的程序才叫运行态,只要是在运行队列中的都交运行态;

1.2阻塞状态

OS管理硬件同样是遵循先描述在组织的原则,所以这些与硬件联系的进程也需要队列来维护,除了运行队列外还需要一个阻塞队列;

为什么需要阻塞队列?

因为外设的速度是很慢的,CPU的运行速度是非常快的,也就是处于运行队列中的进行在一段时间可以执行多次,但是外设可能就反应不过来,所以这个时候进程就需要的等待外设,所以就需要一个阻塞队列在维护等待状态的与外设联系的进程;

1.3挂起状态

挂起状态通常是出现在内存紧张不足的情况下,我们的进程代码和数据,正常情况下下加载到内存中的,但是如果内存资源紧张,OS就会把一些进程的代码和数据再放回到磁盘中,这些置换的进程此时的状态就叫做挂起状态;

出现挂起状态的原因

1.出现挂起状态的原因是内存资源紧张,也就是内存不足,内存里存在着大量的进程,所以一种原因是进程太多,还可能是阻塞进程太多,导致进程没有运行但仍然占用内存;

2.(了解)我们内存中存在一个交换分区,这个分区就是专门处理溢出的资源---硬盘驱动器的一部分,用作交换内存,即RAM的溢出空间;

还需要注意的点: 

1.挂起进程并不需要让你知道,就像你玩那个银行存钱,你存进去的钱不知道被用于什么地方;但是只要你需要的时候,银行就会给你,挂起状态的进程,如果准备调度时,OS会把数据和代码块从磁盘上置换回来;

2.挂起状态的进程的PCB可能会处于挂起队列,等待被唤醒或恢复执行;

二,并发执行与进程切换

调度器将进程轮流调度到CPU上运行,这个过程并不是将一个进程运行完毕才放下的,

原因:

1.如果当前进程是死循环,那么将永远不会结束,如果按照执行完才放下的策略,后面的进程将永远无法被调度;

2.为了保证进程的公平性,每个进程都会占用一个时间片,也就是占用CPU一个时间片的时间就会被放下来,让后面的进程运行,这样就保证了处于运行队列中的每一个进程都有机会被CPU运行;

2.1,CPU并发执行

CPU的执行速度是很快的,在一段时间,运行队列的所有进程都会被执行一遍,多个进程轮流被一个CPU调度,这个就叫做CPU并发执行;

2.2进程切换

每个进程在时间片到达之后,会被调度器从CPU上放下去,让后面的进程放到CPU上运行,这个切换的过程就叫做进程切换;

三,Linux内核管理进程状态的方法

先看一下Linux内核中的状态有哪些?

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

3.1查看进程状态

指令:ps -ajx

3.2R状态

R(running)即运行态:处于运行队列或正在运行的进程;

3.3S状态

S(Sleeping)睡眠状态:这个睡眠是浅度睡眠,也就是可以被唤醒的,通常是等待某一事件的完成;

---->其实就相当于是阻塞状态(与硬件建立联系,等待硬件回应)

我们来验证下:

进程处于R运行态;

我们加上printf试试

我们会发现此时处于S状态,关键就在于此进程与硬件发生交互,可能处于阻塞队列中,也就是可能会处于可中断睡眠状态来等待硬件回应;

3.4D状态

D(Deep Sleep):磁盘休眠状态,也叫做不可中断休眠或不可唤醒状态;这个进程通常是等待IO的完成,但是又等不到IO的完成;

下面 为了方便理解,讲一个故事:

比方说我们现在编译了一段代码,需要将1GB的文件写入磁盘中,内存需要跟磁盘建立联系,磁盘在被写入之前需要判断该行为是否可以被执行,比方说现在磁盘中的空间不足1GB,那么这个请求就应该被驳回,这个过程中我们的内存需要先对磁盘说:“我打算写入1GB的内容,你看看可不可以”  磁盘回复:“那你稍等一下,我看看自己的空间是否足够”   当该信息确认后,然后磁盘回复进程:“我当前空间足够,可以执行” 。然后进程才会通过其对应的代码和数据来将1GB写入磁盘。   所以这个过程有发起也有返回,内存像磁盘申请,磁盘完成后将结果返回给内存,但是这个过程是需要等待的!!

假设当前有大量的进程处于阻塞队列,此时内存不够了,因此操作系统需要杀死一部分进程来保证运行 。当系统压力很大时,依靠内存的辗转腾挪解决不了时,操作系统只能想办法杀死他认为不太重要的进程!

 内存在向磁盘发出请求的时候,在磁盘还没回复是否可行的时候该进程就被操作系统杀死了,所以磁盘想要回复的时候发现该进程不在了,所以就懵圈了。当盘想要回应的时候却发现那个等待自己的进程没有了,那么现在写入失败了怎么办?我是应该继续尝试呢,还是丢掉呢??此时不同的操作系统有不同的做法。

比如是在银行,某些数据丢失导致损失了几个亿!!这个时候法官  叫来了 操作系统、进程、磁盘 三个人,来这个过程应该是谁的错,第一嫌疑人是操作系统,因为操作系统杀进程了,操作系统说:“请问我是否履行了自己的职责,我是否是在比较极端的情况下去杀进程的,我能做的最大努力就是保证操作系统不挂掉!!如果我有错,那我下次再遇到这种情况??我还做不做了?就算我不杀进程,导致操作系统挂了,他数据该丢还是会丢,还会影响其他进程,这个责任又该谁负责呢??”  法官觉得操作系统说得有道理,于是又把矛头转向了第二嫌疑人磁盘,因为磁盘在写入失败的时候擅自把数据丢失了。磁盘说:“这不怪我,我就是个跑腿的,我在写入的时候就告诉他可能会失败了,所以我让他在那里等我的结果,可是他人不见了,而是丢失是因为我还有其他工作得做,如果我有错的话,那我们是不是得把磁盘所有逻辑都改了???”法官觉得磁盘说的也有代理,于是又把矛头转向了进程,此时进程扑通一声跪了下来说:“我是被杀的,我怎么能有错呢?”所以凡是存在争议很大的地方,大部分都是因为制度设置的不合理。所以法官说,你们都回去吧,我把操作系统改一改——>让一些进行在磁盘写入完毕期间,这个进程不能被任何人杀掉,其实就是不接受任何响应,但是D状态不多见因为如果有很多说明系统已经临近崩溃了!!

3.5T状态

T(停止状态):OS可以发送信号SIGSTOP信号来停止进程,这个进程是可以通过OS发送信号SIGCONT继续进程的;

暂停和睡眠的区别:暂停是OS发送信号暂时停止进程运行的,而睡眠是进程等待某事件完成;

指令:kill -l

 这些都是信号,9是刹进程,18是继续开始进程,19是停止进程;

T状态存在的意义:可能是需要等待某种资源,或者是我们单纯不想让该进程运行!!

 应用场景就是gdb,当程序运行起来的时候遇到了我打的一个断点,然后就停下来了,这是这个过程就可以被应用于gdb这个进程在控制被调试的这个进程!

3.6X状态

 X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

3.7Z状态

Z(Zombie):僵尸状态,僵尸即人死僵硬无法动弹,进程层面理解就是进程结束了,然后没有后续工作进程(回收资源);

我们来验证一下:

 前5秒

后5秒

为什么会存在僵尸状态?

一个进程进行完并不是直接把资源释放,而是要暂时维持状态一段时间-->因为父进程要关心子进程的状态;子进程是父进程创建的,创建他的原因就是让他帮父进程完成某项任务,所以事情完成的如何,进度,最后是要汇报给子进程的;

什么时候会发生僵尸状态?

子进程先父进程结束,而父进程并没有回收子进程的资源,这个时候子进程就会保持僵尸状态等待父进程回收;

 如果父进程到了最后也不回收子进程,是不是就会造成泄露?

-->是的,子进程不被回收,那么PCB就会一直存在维护,占用内存,就会造成资源浪费;

3.8孤儿进程

孤儿进程与僵尸进程是反着的,孤儿进程发生的条件是父进程比子进程先结束;

孤儿进程怎么处理呢?

孤儿进程无法被父进程正常回收,就会被系统进程领养,

Ctrl+c无法终止异常进程,底层原理是什么?

ctrl+c的原理是一瞬间父进程被Bash进程回收,所以子进程也就同时在一瞬间被父进程回收掉;

但是如果子进程处于孤儿状态,那么他的PPID就不再是原来的父进程,而是系统进程(PID为1);这时Ctrl+c将不会终止子进程;

 四,进程优先级

4.1优先级理解

为什么要有优先级?

因为资源有限,多个进程之间是竞争的,所以先后顺序是肯定存在的,优先级高的先运行,这将大大的改善系统性能;

OS对优先级的调整是什么?

1.IO操作相关调整:在IO完成后会被适当的提高优先级,因为IO操作通常会让进程处于阻塞状态,当IO完成后提高优先级,能让进程优先尽快处理,提高整体效率;

2.时间片相关调整:进程用完时间片后仍未完成,系统可能会降低其优先级,给其他进程更多机会,避免一个进程长时间占用CPU,保证系统的公平性和响应性;

4.2查看和调整优先级

指令:ps -l

与优先级有关是PRI和NI字段;

PRI(priotity)即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高

NI(nice)其表示进程可被执行的优先级的修正数值

PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice

nice其取值范围是-20至19即[-20,19],一共40个级别。

4.3如何修改优先级

优先级=PRI+NI;

PRI是不可修改的都是80但是我们可以修改nice值,

有两种方法:

一,

1.输入指令top

2,按r

3.输入进程的PID

4.填入nice值

二,

使用renice命令

指令:renice (nice值) -p (进程PID)

五,Linux内核调度算法 

 1.需要维护两个队列按照顺序运行,一个是运行队列,一个是等待队列;时间片到了之后就会转到等待队列;

2.同等优先级的进程遵循先来后到原则;

3.需要维护一个位图,来确定位置

 ——>因为优先级有各种各样的,比方说在100的位置有2个进程,在133的位置有2个进程,但是我们并不能马上知道这几个地方有进程,而是只能通过遍历数组的方式来一个个查看。最后我们最后当数组遍历到结尾的时候才能确定队列位空

用位图大O(1) 调度算法优化 

 ——>只有100-139一共40个级别,我只需要用5个字节一共40个比特位来标记是否存在进程即可,这样我们就可以通过位运算的方法快速找到  队列中存在进程的位置。 最后当位图位0的时候,就说明队列位空了!!


http://www.kler.cn/a/520085.html

相关文章:

  • 【C语言系列】深入理解指针(4)
  • 上海亚商投顾:沪指冲高回落 大金融板块全天强势 上海亚商投
  • 高级java每日一道面试题-2025年01月23日-数据库篇-主键与索引有什么区别 ?
  • arm-linux平台、rk3288 SDL移植
  • “AI教学实训系统:打造未来教育的超级引擎
  • 矩阵快速幂
  • C++——动态管理
  • WinForm保持一个窗口在另一个全屏窗口的上面
  • Redis高阶5-布隆过滤器
  • MFC程序设计(四)窗口创建机制
  • 在php中怎么打开OpenSSL
  • 云服务器快速安装docker, mysql,redis教程
  • 闲来无事复习下基础算法——递归的魅力
  • 【论文阅读】RAG-Reward: Optimizing RAG with Reward Modeling and RLHF
  • Golang并发机制及CSP并发模型
  • mybatis是什么?有什么作用?mybatis的简单使用
  • 低代码系统-产品架构案例介绍、得帆云(八)
  • C#加密方式
  • IoTDB 2025 春节值班与祝福
  • 01.K临近算法
  • VSCode安装+配置
  • Unity3D连接PLC的原理
  • 头歌实训作业 算法设计与分析-贪心算法(第5关:求解流水作业调度问题)
  • 汇编知识点整理
  • 在WSL使用gnome终端
  • TCP协议:互联网数据传输的守护者