Linux:进程调度

简介: Linux:进程调度

进程优先级

查看优先级

在Linux中,进程是有优先级的,我们可以通过指令ps -la来查看:

其中PRI表示priority优先级,在Linux中,优先级的范围是[60, 99]共40个级别。

其中80是优先级的默认值,PRI的值越小,进程的优先级就越高。

Linux之所以把优先级控制在40个,是为了防止有的进程把自己的优先级调的很高,导致一直占用CPU,其他进程得不到资源。这个问题叫做进程饥饿问题。

调整优先级

那么我们要如何调整一个进程的优先级呢?

在刚刚的图示中,在PRI后面还有一个项目,NI,其代表nice值。进程优先级PRINI满足以下公式:

PRI=80+NI

所以我们想要调整进程的优先级PRI,就是要调整nice值。

现在在test.exe可执行程序中执行以下代码:

#include <stdio.h>    
#include <unistd.h>    
#include <stdbool.h>    
    
int main()    
{    
    printf("I am a process, pid = %d\n", getpid());    
    
    while(true)    
    {}    
    
    return 0;                                                                                               
}    

该进程输出自己的PID后,就处于一个死循环状态。

输出结果:

此时进程一直死循环,我们通过ps -la观察一下:

可以看到,现在多了一个PID=23432的进程,也就是我们执行的test.exe,其PRI值为默认值80,现在我们开始修改该进程的nice

  1. 执行top指令,进入资源管理器:

你会进入如下页面:

  1. 按下r键:

r代表你想要改变某个进程的nice,此时白色行上面会出现一个光标,提示你输入想要改变进程的PID

3. 输入PID

输入PID后,现在你就可以改变nice值了:

  1. 输入修改后的NI值:

此处我把nice值设为10,按下回车。

  1. 最后按下q退出管理器

现在我们通过ps -la观察一下:

test.exeNI变成了10,而PRI变成了80 + NI = 90了。


Linux 2.6 内核进程调度队列

现在我们再来看看,进程是如何被调度的,以及优先级是如何起作用的。

此处我以Linux 2.6内核的进程调度队列为例。

CPU中,存在大量的寄存器,比如以下常见的寄存器:

eax/ebx/ecx/edx:用于存储临时数据,比如函数返回值

eds/ecs/fg/gs:段寄存器,区分代码与数据

eip:也就是pc指针,指明当前代码执行到那个位置

浮点数寄存器:浮点数运算

ebp/esp:构建栈区

程序在运行的时候,会存储大量的数据,比如当前执行到哪一行代码,上一个语句运算的结果是什么,函数调用到第几层了,等等。这些数据都存储在CPU的寄存器中。CPU中存储的所有临时数据,叫做硬件上下文

当一个进程从CPU中离开,会把所有的硬件上下文都拷贝走,存储在PCB中,这个过程叫做保护上下文

而当一个进程被再次调度的时候,又会把自己的数据写入CPU中,覆盖原始的寄存器中的数据,这个过程叫做恢复上下文


那么我们再来看看运行队列是如何调度进程的

Linux的运行队列run_queue视图如下:

我们先看到蓝色区域:

其中nr_active表示当前run_queue总共含有几个进程

queue[140]就是运行队列的主体,我们将其划分为两个区间[0, 99]这段区间暂不讲解,[100, 139]这个区间用于放正在排队的进程的PCB.

这个区间刚好有40个元素,而我们的优先级也刚好有40个,也就是说一个优先级的进程对应一个下标。

其实这个数组本质是一个指针数组,类型是task_struct*,即指向PCB类型的指针,每个指针指向一个链表,链表内存储着所有该优先级的进程的PCB

比如优先级为80的进程,都存储在queue[120]指向的链表中

运行队列调度进程的时候,从下标100开始,也就是从高优先级开始调度,然后遍历这个链表,把高优先级的链表执行完,再去执行下一个优先级的链表的进程

bitmap是一个五个元素的int数组,其是一个位图,一个int有32字节,5×32=160,比140大一些。

其用一个位图来表示某个下标对应链表有没有进程,有就是1,没有就是0。此时就可以通过遍历位图,来快速判断一个queue的某个下标位置有没有进程,进而得出要不要去遍历该下标的链表。

那么现在有一个问题,那就是刚刚提到的进程饥饿问题:

假设现在CPU正在执行下标为110的链表的进程,也就是优先级为70的进程,此时刚好又有很多优先级为70的进程进来了,结果CPU一直在执行这个优先级的进程。最后70优先级以后的进程,一直拿不到CPU资源,导致进程饥饿问题。

为了解决该问题,其实run_queue中有两个运行队列,在上图中你会发现,红色区域和蓝色区域的是一模一样的:

这就是两个相同的队列,一个叫做活跃进程队列,一个叫做过期进程队列

active指针指向的队列就是活跃进程队列,expired的指针指向的队列就是过期进程队列

CPU只执行活跃进程队列中的进程,而新来的进程进入过期队列,此时新来的进程就不会影响正在执行的进程,解决了进程饥饿的问题。

当CPU把活跃进程队列的进程执行完后,此时expiredactive指针进行交换,那么活跃进程与过期进程就交换了,此时CPU就去执行新的活跃进程队列。

这样的两个队列轮流执行,一个负责执行,一个负责接受新进程的结构,就解决了进程的饥饿问题

相关文章
|
14天前
|
算法 调度 UED
深入理解操作系统:进程调度与优先级队列
【10月更文挑战第31天】在计算机科学的广阔天地中,操作系统扮演着枢纽的角色,它不仅管理着硬件资源,还为应用程序提供了运行的环境。本文将深入浅出地探讨操作系统的核心概念之一——进程调度,以及如何通过优先级队列来优化资源分配。我们将从基础理论出发,逐步过渡到实际应用,最终以代码示例巩固知识点,旨在为读者揭开操作系统高效管理的神秘面纱。
|
16天前
|
缓存 监控 Linux
linux进程管理万字详解!!!
本文档介绍了Linux系统中进程管理、系统负载监控、内存监控和磁盘监控的基本概念和常用命令。主要内容包括: 1. **进程管理**: - **进程介绍**:程序与进程的关系、进程的生命周期、查看进程号和父进程号的方法。 - **进程监控命令**:`ps`、`pstree`、`pidof`、`top`、`htop`、`lsof`等命令的使用方法和案例。 - **进程管理命令**:控制信号、`kill`、`pkill`、`killall`、前台和后台运行、`screen`、`nohup`等命令的使用方法和案例。
48 4
linux进程管理万字详解!!!
|
7天前
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
43 8
|
11天前
|
算法 调度 UED
深入理解操作系统:进程管理与调度策略
【10月更文挑战第34天】本文旨在探讨操作系统中至关重要的一环——进程管理及其调度策略。我们将从基础概念入手,逐步揭示进程的生命周期、状态转换以及调度算法的核心原理。文章将通过浅显易懂的语言和具体实例,引导读者理解操作系统如何高效地管理和调度进程,保证系统资源的合理分配和利用。无论你是初学者还是有一定经验的开发者,这篇文章都能为你提供新的视角和深入的理解。
32 3
|
13天前
|
人工智能 算法 大数据
Linux内核中的调度算法演变:从O(1)到CFS的优化之旅###
本文深入探讨了Linux操作系统内核中进程调度算法的发展历程,聚焦于O(1)调度器向完全公平调度器(CFS)的转变。不同于传统摘要对研究背景、方法、结果和结论的概述,本文创新性地采用“技术演进时间线”的形式,简明扼要地勾勒出这一转变背后的关键技术里程碑,旨在为读者提供一个清晰的历史脉络,引领其深入了解Linux调度机制的革新之路。 ###
|
15天前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
49 4
|
16天前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####
|
16天前
|
消息中间件 算法 调度
深入理解操作系统:进程管理与调度策略
【10月更文挑战第29天】本文将带领读者深入探讨操作系统中的核心组件之一——进程,并分析进程管理的重要性。我们将从进程的生命周期入手,逐步揭示进程状态转换、进程调度算法以及优先级调度等关键概念。通过理论讲解与代码演示相结合的方式,本文旨在为读者提供对进程调度机制的全面理解,从而帮助读者更好地掌握操作系统的精髓。
30 1
|
16天前
|
算法 调度 UED
深入理解操作系统中的进程调度
【10月更文挑战第29天】探索进程调度的奥秘,本文将带你深入了解在操作系统中如何管理和控制多个并发执行的程序。从简单的调度算法到复杂的多级反馈队列,我们将逐步揭示如何优化系统性能和提高资源利用率。准备好一起揭开进程调度的神秘面纱吧!
|
18天前
|
消息中间件 存储 Linux