Linux·进程概念(下)

news2024/10/5 22:48:43

1. 进程优先级

        优先级就是获得某种资源的先后顺序,因为CPU资源是有限的,因此各个进程之间要去争取CPU的资源。

        那么针对Linux操作系统下的PCB中,也就是task_struct结构体中,使用了int类型的变量记录了每个进程的优先级属性,其中优先级数字越小,代表该进程优先级越高。

        我先随便启动一个进程,来看看优先级

        我们打开一个进程,然后用另一个终端输入指令 ps -al 就可以。

        我们只关注PRI和NI的数值。其中 PRI(priority) 代表Linux进程的最终优先级,NI(nice) 是优先级的nice数据,或者说优先级的修正数据。

        nice在这里可以翻译成 "细微的"。把优先级设计成两个参数一起操控的原因是为了防止因为一些优先级的问题导致进程运行问题,比如如果一个程序的进程正在运行但是我们一下子把PRI调低了,那这个进程还要不要执行下去。因此在修改进程优先级的时候,可以现在nice值上修改,等到操作系统更新优先级的时候就统一把优先级从新设置了。

        ps:这里我们可以看到一个UID的值,这是user id的意思,表示目前是哪个用户在进行这个进程,就像一个学生的学号一样。进程也是通过这个值来判断一个用户对某文件是否有读写权限的。

1.1 修改优先级

        修改优先级在Linux中并不多用,而且不建议修改进程优先级。

        nice值的取值是 [-20, 19] 一共40个值,每次调整都是在PRI为80的基础上进行加减,而不是以原优先级为基础进行调整。也就是说调整优先级的操作更类似于是在重置并修改。

        我们下面用 top(Linux下的任务管理器) 来调整一下优先级

        首先随便启动一个进程,然后在另一台终端上输入top命令,再在top中敲 r ,此时可以看到pid to renie的提示,然后我们就可以输入进程id,再修改nice值了。 

        修改的时候直接输入新nice值

                  】

        然后我们退出top查看一下进程优先级,果然是被改变了。如果在改优先级的时候发现修改请求被拒绝了,那就是权限不够,直接 sudo top 提权打开任务管理器就能改优先级了。

        之所以这个nice值只能在一个可控范围内调整就是为了所有进程尽量均衡的调用,这也是分时操作系统的原则。

2. 进程切换

        每一个进程都有对应的时间片,时间片跑完了就要切换进程,这个就是进程的调度轮转。那时间片到了有可能这个进程还没有跑完,那如何让一个进程可以在任何地方重新调度切换就是关键。

        简单来讲,就是在一个进程将要结束自己的这一时间片时,会将自己的运行数据暂时存储起来带走,等重新轮转到自己的时候,再将运行数据给CPU,继续之前的结果计算。

        在CPU中有很多寄存器,例如ebp、esp、eax、ebx等等。本次我们只关注 eip(pc指针) ir

        ir 寄存器,也叫指令寄存器,其中保存的是正在执行的指令

        eip 也叫pc指针,其中存放的是当前正在执行的指令的下一条指令,若有call这种函数调用,其中也会对应记录。

        CPU内部的寄存器记录的是进程正在执行时的瞬时状态信息数据,我们将这个数据称为上下文数据

        那么进程切换的核心就是进程上下文数据的保存和恢复

        当一个进程要开始进入CPU计算了,首先把main函数入口处的地址放到pc指针处,然后在ir寄存器加载第一条命令,CPU控制器将这条命令拿去分析,有需要时交给运算器去计算。当这段进程的时间片跑完后,会将此时该进程在CPU中运算所留下来的所有痕迹拿出去存起来,痕迹比如ebp、esp中存的数据,ir、eip中运行到哪里的记录。这个存储的地方就是PCB中,以 tss_struct(任务状态段) 一种结构体存在,等重新轮转到这段进程的时候就把任务状态段中的数据重新加载到CPU的对应寄存器中就可以接着上次运行继续了。

3. Linux中的调度算法

        我们之前轮调进程的时候都是在一个运行队列中,按顺序从头到尾轮一个遍,这种调度算法虽然简单,但是完全表现不出进程优先级的效果,因此我们下面浅谈一下Linux内核中写的调度算法时什么样的。

        Linux中的调度算法是基于一种类似哈希表结构实现的。

        首先,Lunix的哈希表或者说运行队列中只有140个元素,其中 0到99 前100个元素位置是留给实时进程的,100到139 后40个元素是给分时进程的,也就是说我们只能通过优先级控制后40个元素的位置。

        其对应方案,也就是哈希函数为 i = pri - 60 + 100 真实进程优先级减60加100,真实进程优先级因为有nice值的限制,只能以80为基础在nice值 [-20, 19] 的范围限制下修改,也就是说真实进程优先级的范围是  [60, 99] ,这个范围经过哈希函数的映射后正好就是 [100, 139]

        之后不同优先级的进程就可以开散列式的打散到各个队列当中,相同优先级的进程就可以如哈希桶一样挂到一起。如此利用哈希表结构完成进程在O(1)时间复杂度内的入运行队列

        然而在实际的进程控制操作中可能会遇到3种情况:1. 进程正常退出    2. 进程跑完时间片  3. 新插入进程。

        进程正常退出就是走Z状态再走X状态,父进程释放其资源完成退出。但是到插入进程的话会有一点问题,如果有人一直恶意、频繁的插入优先级非常高的新进程,就会导致操作系统一直在执行新进程,而永远没有机会执行其他优先级较低的进程,这种情况下那些一直执行不到的进程就被称为饥饿进程

        那么为了避免饥饿进程的发生,Linux调度算法种引入了一个活跃进程过期进程的处理方案,正在进行的进程哈希表被称为活跃进程的哈希表新插入的进程和跑完时间片的进程都会被放入过期进程的哈希表中,最后活跃进程的哈希表完全都跑完了,也就是说活跃进程的哈希表为空后,交换活跃进程与过期进程的哈希表,如此循环。也就是说Linux调度算法中用两个哈希表作为基础,解决了饥饿进程的问题。

        但是两个哈希表仅仅是基础,它们分别又被外面包了一层结构体,两个结构体组成了一个2元素的数组用来集中控制,最后数组外面又包了一层结构体,最后这一层结构体才被叫做运行队列runqueue

        刚才说的包来包去的很复杂,我们照着上图捋一遍。

        首先存放着进程PCB的哈希表被包在结构体queue中,同时在这个结构体中有表示哈希表一共存放多少进程的个数的nr_active变量,位图bitmap[5],这是一个有5个int元素的数组,作用是帮助在O(1)时间复杂度之内找到一个有效的哈希桶,具体怎么操作的我们后面详谈。

        之后这个两个queue结构体被封装进一个两元素的数组,便于统一管理。

        最后数组、活跃进程指针、过期进程指针,被封装到运行队列结构体中。两个指针分别指向数组的两个元素,这两个元素中就是活跃进程的哈希表和过期进程的哈希表,此时完成逻辑闭环。

        位图bitmap[5]是利用比特位标识哈希表中某个位置有没有哈希桶,5个int一共40个字节,160个bit位,后20个比特位没有意义,不看,只看前140个bit位。第几号比特位为1,表示哈希表中第几位有哈希桶,这个哈希桶不一定只有一共,可能这个位置坠了一串哈希桶,就说明这个位置有一串优先级一样的进程。

        在寻找有效哈希桶的时候可以先看bitmap5个数组元素的值,如果5个元素都为0,说明现在没有进程在运行状态。如果不为0,就接用 n&(n-1) 的思路快速找到第一个为1的比特位,大概操作就是用 n&(n-1)的值 按位异或^n,就可以直接暴露出第一个为1的比特位,分析这个值,可以得到第几号比特位为1。

        n&(n-1)的思路在下面这个连接中

C语言·操作符详解-CSDN博客

        最终找到有效哈希桶,如果是一串哈希桶,就从第一个开始运算并头删,直到这组哈系统全部调度完毕。如此可以在O(1)时间复杂度内利用位图完成有效哈希桶搜索。

        如此O(1)级别的进程哈希桶插入,O(1)级别的哈希桶搜索,最成就为Linux的O(1)级别进程调度算法

4. Linux中的数据结构

        我们之前在学习数据结构的时候,比如链表,一共节点中既要存贮数据(属性字段),又要有next、prev指针(连接字段),但是在Linux源代码中对于数据结构的处理是只有连接字段,没有属性字段的。

        就是说只提供链条,而我们要把链条手动绑在各个结构体节点上,我们以双向链表举例子。

        在需要由数据结构链接起来的结构体节点之间用数据结构的链条绑定起来,而不是直接把节点绑定起来。

        这么做的意义是可以把同一种结构体节点同时不同的数据结构方案绑定起来,而不用写多份节点形式来适应不同的绑定方案。

        因为绑定的是结构体的成员变量,因此如何通过成员变量找到改成员所属的结构体就十分重要。解决方案就是计算该成员的偏移量,通过 所属结构体地址 = 该成员地址 - 偏移量 的公式可以计算出。C语言库中提供了一个宏来帮助计算偏移量 offsetof (type,member); <stddef.h>

        至于偏移量和结构体内存分配方案是什么可以转到:C语言·自定义类型:结构体-CSDN博客

        如果想要自己计算偏移量,可以参考这个思路

                ​​​​​​​        ​​​​​​​        

        以内存地址为0的地方做结构体基准点,直接取成员变量,其内存大小就是改成员的偏移量,如果用该成员的真实地址减去偏移量,就能得到结构体的起始地址。将得到的结构体真实起始地址拿去强转成对应类型,比如将地址强转成 struct A 类型就可以正常使用这个结构体了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2190661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WIFI网速不够是不是光猫的“路由模式”和“桥接模式”配置错了?

光猫&#xff08;光纤调制解调器&#xff09;是一种用于将光纤信号转换为数字信号的设备&#xff0c;通常用于家庭或企业网络中。光猫可以在不同的工作模式下运行&#xff0c;其中最常见的两种模式是“路由模式”和“桥接模式”。以下是这两种模式的详细解释及其优缺点。 一、路…

python实现单例模式的常用三种方法-基于__new__/使用装饰器以及Python中的值类型、引用类型以及类的静态变量、读取进程和线程ID

一、python实现单例模式的常用三种方法-基于__new__,使用装饰器 涉及到类的使用就会有类的实例化&#xff0c;就会有类单例实现的需求&#xff0c;因为重复实例化会浪费资源。python中的单例模式与别的语言相比&#xff0c;单例实现的方法更丰富。虽然python实现单例的模式的方…

MobaXterm使用

Linux连接工具MobaXterm详细使用教程-CSDN博客

Elasticsearch学习笔记(五)Elastic stack安全配置二

一、手动配置http层SSL 通过前面的配置&#xff0c;我们为集群传输层手动配置了TLS&#xff0c;集群内部节点之间的通信使用手动配置的证书进行加密&#xff0c;但是集群与外部客户端的http层目前还是使用的自动配置&#xff0c;集群中HTTP的通信目前仍然使用自动生成的证书ht…

【韩顺平Java笔记】第7章:面向对象编程(基础部分)【227-261】

文章目录 227. 重载介绍228. 重载快速入门229. 重载使用细节230. 重载课堂练习1231. 232. 重载课堂练习2,3233. 可变参数使用233.1 基本概念233.2 基本语法233.3 快速入门案例 234. 可变参数细节235. 可变参数练习236. 作用域基本使用237. 作用域使用细节1238. 作用域使用细节2…

Docker安装部署和常用命令

Docker 是一种开源的平台&#xff0c;旨在帮助开发者和运维人员更轻松地创建、部署和运行应用程序。通过将应用程序及其依赖项打包到一个名为容器的标准化单位中&#xff0c;Docker 提供了一种轻量级的虚拟化解决方案。与传统虚拟机相比&#xff0c;Docker 容器可以在同一主机上…

GoogleNet原理与实战

在2014年的ImageNet图像识别挑战赛中&#xff0c;一个名叫GoogLeNet 的网络架构大放异彩。以前流行的网络使用小到11&#xff0c;大到77的卷积核。本文的一个观点是&#xff0c;有时使用不同大小的卷积核组合是有利的。 回到他那个图里面你会发现,这里的一个通过我们最大的池化…

12条职场经验总结

01 事干得好不好尚且不说&#xff0c;但是话一定要说得漂亮。 比如&#xff0c;当领导给你安排工作的时候&#xff0c;你一定要非常积极地响应&#xff0c;拍着胸脯跟领导说“放心吧”。至于后续到底怎么干&#xff0c;再结合实际情况有的放矢地把握。 02 当别人夸奖你的时…

记录使用crypto-js、jsencrypt实现js加密的方法

实用为主&#xff0c;直接上干货。 使用工具&#xff1a;pycharm专业版2020.3.2。 记录通过crypto-js模块、jsencrypt模块两种方式实现加密。 本文在pycharm中新建一个项目&#xff0c;一步一步记录实现步骤。 一、新建pycharm项目并新建两个js文件&#xff0c;分别命名为c…

Python 工具库每日推荐 【Requests】

文章目录 引言Python网络库的重要性今日推荐:Requests工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例1:获取天气信息案例分析案例2:文件上传案例分析高级特性会话和Cookie处理自定义请求头超时设置代理设置扩展阅读与资源优缺点分析优点:缺…

Markdown 语法详解大全(超级版)(三)——甘特图语法详解

Markdown 语法详解大全(超级版)&#xff08;三&#xff09;——甘特图语法详解 Markdown 语法详解大全(超级版)&#xff08;一&#xff09; Markdown 语法详解大全(超级版)&#xff08;二&#xff09; Markdown 语法详解大全(超级版)&#xff08;三&#xff09; Markdown 语法…

[Linux#61][UDP] port | netstat | udp缓冲区 | stm32

目录 0. 预备知识 1. 端口号的划分范围 2. 认识知名端口号 3. netstat 命令 4. pidof 命令 二.UDP 0.协议的学习思路 1. UDP 协议报文格式 报头与端口映射&#xff1a; 2. UDP 的特点 面向数据报&#xff1a; 3. UDP 的缓冲区 4. UDP 使用注意事项 5. 基于 UDP 的…

栈的介绍与实现

一. 概念与结构 栈&#xff1a;⼀种特殊的线性表&#xff0c;其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶&#xff0c;另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out的原则。 压栈&#xff1a;栈的插…

平面电磁波(解麦克斯韦方程)电场相位是复数的积分常数,电场矢量每个分量都有一个相位。磁场相位和电场一样,这是因为无损介质中实数的波阻抗

注意无源代表你立方程那个点xyzt处没有源&#xff0c;电场磁场也是这个点的。 j电流面密度&#xff0c;电流除以单位面积&#xff0c;ρ电荷体密度&#xff0c;电荷除以单位体积。 j方程组有16个未知数&#xff0c;每个矢量有三个xyz分量&#xff0c;即三个未知数&#xff0c;…

k8s的简介和部署

一、k8s简介 在部署应用程序的方式上面&#xff0c;主要经历了三个阶段&#xff1a; 传统部署:互联网早期&#xff0c;会直接将应用程序部署在物理机上优点:简单&#xff0c;不需要其它技术的参与缺点:不能为应用程序定义资源使用边界&#xff0c;很难合理地分配计算资源&…

fiddler抓包18-1_导出jmeter脚本(jmx文件)

课程大纲 方法1 ① 下载2个扩展文件&#xff0c;FiddlerExtensions.dll和FiddlerExtensions.pdb&#xff0c;到Fiddler根目录中的“ImportExport”下&#xff0c;重启Fiddler。 下载链接: https://pan.baidu.com/s/1qtLoaiTd-VfHFb3UIPoSZw?pwdtwcu提取码: twcu ② Fiddler导…

UIAbility组件

一、作用 UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个UIAbility组件 1、每一个UIAbility组件实例都会在最近任务列表中显示一个对应的任务。 如果开发者希望在任务视图中看到一个任务,建议使用“一个UIAbility+多个页面”的方…

Qt教程(002):Qt项目创建于框架介绍

二、创建Qt项目 2.1 创建项目 【1、New Project】 【2、选择Qt Widgets Application】 【3、设置项目名称和保存路径】 注意&#xff0c;项目名称和路径不要带中文。 【4、选择QWidget】 带菜单栏的窗口QMainWindow空白窗口QWidget对话框窗口QDialog 【5、编译】 2.2 项目框…

No.3 笔记 | Web安全基础:Web1.0 - 3.0 发展史

大家好&#xff01;作为一个喜欢探索本质的INTP&#xff0c;我整理了一份简明易懂的Web安全笔记。希望能帮助你轻松掌握这个领域的核心知识。 这份笔记涵盖了Web发展的历程&#xff0c;从静态的Web 1.0到智能化的Web 3.0。我们将探讨URL和HTTP协议&#xff0c;揭示它们在网络中…

【深度学习基础模型】神经图灵机(Neural Turing Machines, NTM)详细理解并附实现代码。

【深度学习基础模型】神经图灵机&#xff08;Neural Turing Machines, NTM&#xff09;详细理解并附实现代码。 【深度学习基础模型】神经图灵机&#xff08;Neural Turing Machines, NTM&#xff09;详细理解并附实现代码。 文章目录 【深度学习基础模型】神经图灵机&#xf…