进程管理(十四)–linux进程管理

  • Post author:
  • Post category:linux




1 linux进程分类

当涉及有关调度的问题时, 传统上把进程分类为”I/O受限(I/O-dound)”或”CPU受限(CPU-bound)”.

类型 别名 描述 示例
I/O消耗性 I/O-Bound 频繁进行I/O处理,并花很多时间等待I/O操作完成 键盘等待输入、写磁盘
CPU消耗性 CPU-Bound 花费大量时间进行数字计算,一直占用CPU 大量数学计算

另外一种分法把进程区分成三类

类型 描述 示例
交互式进程 此进程经常需要与用户进行交互,因此需要花费很多时间等待键盘、鼠标、触摸屏等操作,当接受了用户的输入后,进程必须被很快唤醒,否则用户就会抱怨系统卡顿,这类进程的特点就是响应时间越短越好 shll,文本编辑程序和图形应用程序
批处理进程 此类进程不必与用户交互,因此经常在后台运行,因为这类进程不必很快响应,因此常受调度器程序的怠慢,这类进程的特点是会占用比较多的系统资源 科学计算、编译代码
实时进程 这样的进程对整体时延有严格的要求,不能被低优先级的进程阻塞 视频播放等



1.2 linux优先级和分类

操作系统的经典的进程调度算法是基于优先级调度的,优先级的核心思想就是把进程按照优先级进行分类,紧急的进程优先级高,不紧急、不重要的进程优先级低。调度器总是从就绪队列中选择优先级高的进程进行调度,而且优先级高的进程分配时间片会比优先级低的进程长,这体现了一种等级制度。

所以进程优先级代表了进程需要运行的

紧急程度

和需要

更多的运行时间片

,linux操作系统最早开始采用nice值来调整进程的优先级。nice值的思想是要对其他进程友好,就需要降低优先级来支持其他进程消耗更多的处理器时间。

nice值的范围是 【-20 , 19】, 默认值是0,nice值越大,优先级反而越低,nice值越小,优先级越高

nice值为-20表明这个进程非常重要,优先级最高;而nice值是19,表明允许其他进程比这个进程优先享有宝贵的CPU资源

内核使用0-139数值表示进程优先级,数值越小,优先级越高。优先级0

99给实时进程使用,100

139给普通进程使用。另外,在用户空间中有一个传统的变量nice,用于映射普通进程的优先级,即100~139


linux按照优先级分为两类进程


  • 实时进程:

    要求最快被响应,比如视频、工业机器控制程序,

    其优先级为0 ~ 99

  • 非实时进程

    :即普通进程,我们大部分程序使用的,

    其优先级为100 ~ 139

    其还可以细分为两类

    • 交互式进程,需要响应前台请求
    • 后台批处理进程

在这里插入图片描述

linux内核中task_struct数据结构中使用了4个成员描述进程的优先级

在这里插入图片描述

字段 含义
prio 进程的动态优先级,唯一被调度器使用的优先级字段,其依赖于normal_prio字段,调度器在运行期间可调整改值
static_prio 1. 普通进程的静态优先级,仅能通过nice值修改,取值为【100,139】,值越小优先级越高

2. 启动时分配,不会随着时间改变,用户可以通过Nice()或sched_setscheduler()等系统调用来修改
normal_prio 在创建进程时,会继承父进程的normal_prio,对于普通进程来说,改值等同于static_prio,对于实时进程,会根据rt_priorty重新计算normal_prio
rt_priority 实时进程的优先级,取值为[0,99],



1.3 linux权重

linux内核除了使用优先级来表示进程的轻重缓急之外,在实际调度器中还是用了权重的概念来表示进程的优先级,为了计算方便,内核约定nice值为0的进程权重为1024,其他的nice值对应的进程权重值可以通过查表的方式来获取,内核预先计算好了一个表sched_prio_to_weight,表的下标对应Nice值为[-20 ~ 19]

在这里插入图片描述



2. linux调度时机

对于调度器,一个很重要的时调度时机问题,在什么情况下,什么时候发生调度?也就是说在什么情况下,什么时候,把现在占用CPU的进程替换下来,根据进程生命周期的图示,

在这里插入图片描述

内核运行调度程序的条件为

  • 进程从运行状态切换到就绪状态或者等待状态
  • 进程被终结了,就需要从就绪队列中选择下一个进程进行运行

在这里插入图片描述

同时哪些场景不能发生调度呢?


  • 在中断处理过程中:

    中断处理过程,与硬件密切相关,很难做到中断处理过程进行进程切换

  • 在内核程序临界区:

  • 在原子操作过程中:


非抢占内核和抢占内核

在不支持内核抢占的系统中,进程/线程一旦运行于内核空间,就可以一直运行,直到他主动放弃或者耗尽时间片为止,这样就会导致非常紧急的进程或线程长时间得不到运行。

例如,当外部来了一个中断,中断程序程序处理完后,需要一个用户程序B对此进程进行进一步处理。而此时进程A正在使用系统调用进入内核态,那么只有等到A从系统调用返回,内核进行调度,B才有可能被运行。假设A的系统调用占用CPU的时间为T,这个T大于用户要求的响应时间,那么这个系统就不够实时

为了提高Linux的实时性。在linux2.6中引入了“Kernel preemption”(内核抢占调度模式)。并很好的解决了这个问题。一句话就是抢占式内核可以在进程处于内核态时,进行抢占。

为保证Linux内核在以上情况下不会被抢占,抢占式内核使用了一个变量preempt_count,称为内核抢占计数。这一变量被设置在进程的thread_info结构中。每当内核要进入以上几种状态时,变量preempt_count就加1,指示内核不允许抢占。每当内核从以上几种状态退出时,变量preempt_count就减1,同时进行可抢占的判断与调度。

抢占式内核什么时候能发生调度呢?

  • 中断请求被服务历程响应完成,在返回之前被中断的进程时,可以根据需要进行调度
  • 一系统抢占式的调度器函数:preempt_schedule;preempt_schedule_irq。它们都是调用schedule来完成调度的
  • 同样的当时间片用完,进程处于就绪等待状态的时候,会发生调度

在支持内核抢占的系统中,某些特例下是不允许内核抢占的:

  • 内核正进行中断处理。进程调度函数schedule()会对此作出判断,如果是在中断中调用,会打印出错信息。
  • 内核正在进行中断上下文的Bottom Half(中断的底半部)处理。硬件中断返回前会执行软中断,此时仍然处于中断上下文中。
  • 进程正持有spinlock自旋锁、writelock/readlock读写锁等,当持有这些锁时,不应该被抢占,否则由于抢占将导致其他CPU长期不能获得锁而死等。
  • 内核正在执行调度程序Scheduler。抢占的原因就是为了进行新的调度,没有理由将调度程序抢占掉再运行调度程序。

在这里插入图片描述



3. linux调度策略

根据什么准则挑选下一个进入运行的进程。从running的进程队列中找出一个进程,来占用CPU,让它运行。

linux调度依赖于调度策略,Linux内核把相同的调度策略抽象成调度类(schedule class)。不同类型的进程采用不同的调度策略,目前Linux内核默认实现了5中调度类,分别是stop、deadline、realtime、CFS和idle,他们分别使用sched_class来实现,并且通过next指针串联在一起

调度类 调度策略 使用范围 说明
stop 最高优先级的进程,比deadline进程优先级高 1. 可以抢占任何进程

2. 在每个CPU上实现一个名为”migration/N”的内核线程,说明该线程的优先级最高,可以抢占任何进程的运行,一般用来运行特殊的功能

3. 用于负载均衡机制中的进程迁移、softlockup检测、cpu热插拔、RCU等
deadline SCHED_DEADLINE 最高优先级的实时进程,优先级为-1 用于调度有严格要求的实时进程,如视频编解码
realtime SCHED_FIFO

SCHED_RR
普通实时进程,优先级为0 ~ 99 用于普通的实时进程
CFS SCHED_NORMAL

SCHED_BATCH

SCHED_IDLE
普通进程,优先级为100 ~ 139 由CFS来调度
idle 最低优先级的进程 当就绪队列中没有其他的进程时,进入idle调度类,idle调度器会让CPU进入低功耗模式

用户空间程序 可以使用调度策略接口函数(sched_setscheduler())来设定用户进程的调度策略,linux内核对于调度策略定义如下:

在这里插入图片描述



4. 总结

在这里插入图片描述



版权声明:本文为u012489236原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。