2024-09-22 进程优先级,进程切换

一、僵尸状态 & 孤儿进程

进程退出:内核数据结构(task_struct 维护)+ 代码和数据(直接释放)

  1. 代码不会执行了
    首先可以立即释放的就是进程对应的程序信息数据。
  2. 进程退出要有退出信息(进程的退出码),其保存在自己的task_struct的内部。
    结构体 ➡️ 成员属性 ➡️ 退出信息(int code, 其他)
  3. 管理结构task_struct必须被OS维护起来,方便用户未来获取进程退出的信息。

先创建内核数据机构再加载代码和数据,即使代码和数据没加载进来,创建内核数据结构后进程即被创建,只是不会被调度。

#include <stdio.h>
#include <unistd.h>int main(){printf("父进程运行:pid = %d,ppid = %d\n", getpid(), getppid());pid_t id = fork();if(id == 0){//子进程int cnt = 10;while(cnt){printf("循环第%d次,子进程对应的 pid = %d, ppid = %d\n", 11 - cnt, getpid(), getppid());sleep(2);--cnt;}}else{//父进程while(1){printf("父进程对应的 pid = %d\n", getpid());sleep(1);}}return 0;
}

通过如下指令查看进程状态:
while :; do ps ajx | head -1; ps ajx | grep myproc; sleep 1; done

   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND617150  617285  617285  617123 pts/1     617285 S+    1000   0:00 ./myproc617285  617286  617285  617123 pts/1     617285 S+    1000   0:00 ./myproc617270  617361  617360  617253 pts/2     617360 S+    1000   0:00 grep --color=auto myprocPPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND617150  617285  617285  617123 pts/1     617285 S+    1000   0:00 ./myproc617285  617286  617285  617123 pts/1     617285 Z+    1000   0:00 [myproc] <defunct>617270  617366  617365  617253 pts/2     617365 S+    1000   0:00 grep --color=auto myproc

发现子进程进入僵尸状态(Z:维护自己的task_struct,方便未来父进程读取退出状态)。
如果没人管,就会一直维持僵尸状态(task_struct一直存在会消耗内存,造成内存泄漏!)。
默认没人管怎么处理?一般需要父进程读取子进程信息,子进程才会自动退出。

语言层面的内存泄漏问题,如果在常驻内存的进程中出现,影响比较大。

父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
父进程先退出,子进程就称之为“孤儿进程”,孤儿进程被1号 initdsystemd 进程领养、回收。


二、【总结】Linux下的进程状态及其转换过程

1. 进程状态的分类

在Linux中,进程通常会处于以下几种状态之一:

  • R (Running): 运行态,表示进程正在运行或准备运行。
  • S (Sleeping): 睡眠态,分为两种:
    • 可中断睡眠态(Interruptible Sleep,S):进程正在等待某个事件或资源,收到信号后可被唤醒。
    • 不可中断睡眠态(Uninterruptible Sleep,D):进程正等待设备I/O等系统资源,不能被信号中断唤醒。
  • T (Stopped): 停止态,进程被暂停执行,如收到 SIGSTOP 信号或在调试过程中被暂停。
  • Z (Zombie): 僵尸态,进程已经终止,但其父进程尚未调用 wait() 系统调用来获取它的退出状态。
  • X (Dead): 已终止,进程结束且系统已清理其所有资源。

2. 进程状态转换过程

(1)创建进程
  • 初始状态:R(Running)
    • 当调用 fork()clone() 系统调用时,一个新的子进程会被创建。新进程最初处于运行态(R),并继承父进程的资源和执行环境。
(2)运行态和睡眠态的转换
  • R → S(可中断睡眠态)

    • 进程在等待某些资源或事件时会进入可中断睡眠态。比如,当进程请求磁盘I/O或等待网络数据时,它会调用 sleep()wait() 系统调用,导致状态从运行态转换为睡眠态。
    • 进程在此状态下可以被信号唤醒。
  • S(可中断睡眠态)→ R(Running)

    • 当进程等待的事件发生时(如I/O操作完成),或当它收到信号时,进程将被唤醒,状态转换为运行态。
  • R → D(不可中断睡眠态)

    • 进程在等待设备硬件响应或内核中的某些特定事件时,可能进入不可中断睡眠态(如等待磁盘I/O)。这种状态下的进程不能被信号唤醒。
  • D → R(Running)

    • 当设备操作或资源可用时,不可中断睡眠态的进程会被内核唤醒,并返回运行态。
(3)运行态和停止态的转换
  • R → T(Stopped)

    • 进程接收到 SIGSTOPSIGTSTP 信号时会暂停执行,进入停止态。调试过程中,进程被暂停也会处于此状态。
  • T → R(Running)

    • 进程收到 SIGCONT 信号后可以恢复运行,状态从停止态转换为运行态。
(4)僵尸进程的产生及清理
  • R → Z(Zombie)

    • 当进程完成执行并调用 exit() 函数后,它的状态会变为僵尸态。进程已经终止,但它的进程表条目依然存在,直到父进程通过 wait()waitpid() 系统调用收集其退出状态。
  • Z → X(Dead)

    • 当父进程通过 wait()waitpid() 获取到僵尸进程的退出状态后,内核会释放僵尸进程的所有资源,进程真正终止。

3. 进程状态的影响因素

进程状态的转换主要受以下因素影响:

  • 系统资源:进程可能因为等待系统资源(如I/O、内存、锁)而进入睡眠态。
  • 调度器:进程何时运行取决于调度器的策略,如时间片的分配、优先级等。
  • 信号:进程可以通过信号进入停止态或被唤醒等。

三、进程优先级

1. 是什么?获得某种资源的先后顺序

例:排队的本质就是为了确认优先级,资源从打饭的窗口获取

2. 为什么?

因为目标资源比较少

权限:能不能的问题;优先级:已经能了,谁先谁后的问题

3. 怎么办?

task_struct ➡️ 优先级属性 ➡️ 几个特定的int类型变量来表示优先级
优先级数字越小代表优先级越高

用指令 ps -la

F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  618246  618229  0  80   0 -  2585 do_wai pts/1    00:00:00 su
4 S  1000  618247  618246  0  80   0 -  2225 do_wai pts/1    00:00:00 bash
0 S  1000  619020  618247  1  80   0 -   694 wait_w pts/1    00:00:00 prio
4 R     0  619021  618979  0  80   0 -  2518 -      pts/2    00:00:00 ps

PRI:Linux进程的优先级
NI:优先级的nice数据
最终优先级 = pri(默认/旧的)+ NI(优先级的修正数据)

UID即用户ID,揭示了进程是由谁启动的

  1. 文件会记录拥有者、所属组和对应的权限
  2. Linux 中一切皆文件
  3. 所有操作都是进程操作,进程会记录其启动者

    1.3.比对就是权限的基本控制原则

进程竞争的是CPU资源


3.1 修改优先级(非高频操作且不建议修改)

top命令 ➡️ r ➡️ 按照提醒修改即可(注意OS禁止频繁修改和没有权限修改)

$ ps -al
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  621113  621089  0  80   0 -  2585 -      pts/1    00:00:00 su
4 S  1000  621114  621113  0  80   0 -  2199 do_wai pts/1    00:00:00 bash
4 S     0  621186  621170  0  80   0 -  2585 -      pts/2    00:00:00 su
4 S  1000  621187  621186  0  80   0 -  2199 do_wai pts/2    00:00:00 bash
0 S  1000  621239  621114  0  80   0 -   694 hrtime pts/1    00:00:00 pri
0 R  1000  621240  621187  0  80   0 -  2518 -      pts/2    00:00:00 ps

如果设定nice值为100

F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  621113  621089  0  80   0 -  2585 -      pts/1    00:00:00 su
4 S  1000  621114  621113  0  80   0 -  2199 do_wai pts/1    00:00:00 bash
4 S     0  621186  621170  0  80   0 -  2585 -      pts/2    00:00:00 su
4 S  1000  621187  621186  0  80   0 -  2199 do_wai pts/2    00:00:00 bash
0 S  1000  621239  621114  0  99  19 -   694 hrtime pts/1    00:00:00 pri
0 R  1000  621245  621187  0  80   0 -  2518 -      pts/2    00:00:00 ps

结果说明 nice值最大为19


如果设定nice值为-100

root@hcss-ecs-2ff4:/home/usr1/mylinux/F0922# ps -al
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  621113  621089  0  80   0 -  2585 do_wai pts/1    00:00:00 su
4 S  1000  621114  621113  0  80   0 -  2199 do_wai pts/1    00:00:00 bash
4 S     0  621186  621170  0  80   0 -  2585 do_wai pts/2    00:00:00 su
4 S  1000  621187  621186  0  80   0 -  2199 do_wai pts/2    00:00:00 bash
0 S  1000  621247  621114  0  60 -20 -   694 hrtime pts/1    00:00:00 pri
4 S     0  621254  621187  0  80   0 -  2649 do_wai pts/2    00:00:00 su
4 S     0  621255  621254  0  80   0 -  1909 do_wai pts/2    00:00:00 bash
4 R     0  621263  621255  0  80   0 -  2518 -      pts/2    00:00:00 ps

结果说明 nice值最小为20


NI取值范围为[-20, 19]
NI在可控范围内:因为分时操作系统在进行进层调度时要做到尽可能公平
pri(最终)= pri(default 80)+ nice 修改实质上是重置

  • 竞争性:系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  • 独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰
  • 并行:多个进程在多个CPU下分别,同时进行运行,这称之为并行(任何时刻)
  • 并发:多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
    (在一个时间段内,多个进程代码在“同时”推进)

四、进程切换

1. 引入

(1)每个进程都有时间片,时间片到了,进程就该被切换
(2)Linux是基于时间片进行调度轮转的
(3)一个进程在时间片到了的时候并不一定跑完的,可在任何地方被重新调度切换

2. 进程切换

  • 保存上下文数据:保留历史运行痕迹
  • 恢复上下文数据:保留不是目的,而是手段,未来恢复才是目的

(1)进程在运行时会有很多的临时数据都在CPU的寄存器中保存
CPU怎么知道读到哪一行代码了?
eip(pc):当前执行指令的下一条指令的地址(pc = 当前地址 + 读进来的指令长度)
ir:指令寄存器,保存的是正在执行的指令
task_struct 里有程序计数器(pc 指针)
(2)CPU内部寄存器的数据是进程执行时的瞬时状态信息数据,该数据就是进程的上下文数据(随时随地都在高频变化)
(3)CPU内有很多寄存器(一套寄存器),但寄存器 ≠ 寄存器里面的数据(当前进程的上下文数据)

进程切换的核心就是上下文数据的保存和恢复
不做保护无法完成多进程的调度和切换

所有进程都要做如下工作
切走:将相关寄存器的内容保存起来
切回:将历史保存的寄存器数据恢复到寄存器中

意味着每次切换保存完上下文时,CPU都是全新的

3. 细节理解

  • 每个进程都要有自己的上下文数据,但CPU内部只有一套寄存器,该套寄存器被多个进程共享使用
  • 上下文数据保存在哪里?在内存里,进程的上下文寄存器数据,只要保存到当前进程的PCB中就可以了,早期Linux是存在tss_struct

五、调度

真实进程优先级[60, 99]
Linux真实的调度算法在这里插入图片描述
数组queue[140]:存放 struct task_struct* 指针,共140个元素
前100个下标对应的第0~99个元素给实时进程使用的
如果一个进程的优先级pri = 61,应该怎么放?
挂队列在下标为pri - startpri(60) + 100的位置(即 61 - 60 +100 = 101)
hash桶:相同优先级的进程会被挂接到一起

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

六西格玛设计DFSS方法论在消费级无人机设计中的应用——张驰咨询

本文基于六西格玛设计方法论&#xff0c;对消费级无人机的设计流程进行系统化研究&#xff0c;探讨如何通过六西格玛设计的理念、工具和方法提升无人机产品的设计质量和市场竞争力。文章从市场定位、客户需求分析出发&#xff0c;深入到关键KPI指标的制定&#xff0c;并逐步阐述…

【网络安全】漏洞案例:提升 Self-XSS 危害

未经许可,不得转载。 文章目录 Self-XSS-1Self-XSS-2Self-XSS-1 目标应用程序为某在线商店,在其注册页面的First Name字段中注入XSS Payload: 注册成功,但当我尝试登录我的帐户时,我得到了403 Forbidden,即无法登录我的帐户。 我很好奇为什么我无法登录我的帐户,所以我…

前端高频面试题2024/9/22(偏项目问题--通用后台管理系统)

文章目录 一.前端项目概述1.系统登录注册模块1.对注册的密码进行加密 &#xff08;使用加密中间件bcrypt.js&#xff09;2.登录成功后返回token3.前端登录页面有用到弹性布局&#xff0c;ref和reactive4.登录头像&#xff1a;文件上传 2.系统设置模块2.系统首页模块&#xff08…

使用electron+vue开发桌面应用

electron是什么 electron由Node.jsChromiumNative APIs构成。你可以理解成&#xff0c;它是一个得到了Node.js和基于不同平台的Native APIs加强的Chromium浏览器&#xff0c;可以用来开发跨平台的桌面级应用。 它的开发主要涉及到两个进程的协作——Main&#xff08;主&#x…

Java通过RAG构建专属知识问答机器人_超详细

RAG&#xff1a;融合检索与生成的文本精准生成技术 检索增强生成&#xff08;RAG&#xff09;是一种技术&#xff0c;它通过结合检索模型和生成模型来提高文本生成的准确性。具体来说&#xff0c;RAG首先利用检索模型从私有或专有的数据源中搜索相关信息&#xff0c;然后将这些…

编程练习7 5G网络建设

需要用到并查集的相关知识&#xff1a;可以参考如下链接 并查集详解&#xff08;原理代码实现应用优化&#xff09;-CSDN博客 #include<iostream> #include<algorithm> #include<vector>using namespace std;vector<int> split(string params_str) {…

ICT产业新征程:深度融合与高质量发展

在信息时代的浪潮中&#xff0c;每一场关于技术革新与产业融合的盛会都闪耀着智慧的光芒&#xff0c;引领着未来的方向。9月25日&#xff0c;北京国家会议中心内&#xff0c;一场聚焦全球信息通信业的顶级盛事——第32届“国际信息通信展”&#xff08;PT展&#xff09;隆重拉开…

【LwIP源码学习3】TCP协议栈分析——数据接收流程

前言 本文介绍代码在lwip的tcp_in.c文件中&#xff0c;主要介绍TCP协议栈中数据的接收流程。 正文 1、一个正常的TCP数据&#xff0c;首先会传入到 tcp_input(struct pbuf *p, struct netif *inp)函数&#xff0c;其中指针p指向传入的数据流。 2、从数据流中获取TCP头部 …

通过Express + Vue3从零构建一个用户认证与授权系统(二)数据库与后端项目搭建与实现

前言 上一篇完成了系统的相关设计文档的编写&#xff0c;本文将详细介绍如何一步步使用 TypeScript 和 Express 搭建一个模块化、类型安全的用户认证与授权系统&#xff0c;包括数据库设计、后端项目搭建、用户认证、角色与权限管理、错误处理以及 Swagger 文档集成。 项目准…

【ubuntu】ubuntu20.04安装cuda12.6与显卡驱动

目录 1.安装cuda12.6 2.安装显卡驱动 1.安装cuda12.6 https://developer.nvidia.com/cuda-toolkit-archive https://developer.nvidia.com/cuda-12-6-0-download-archive?target_osLinux&target_archx86_64&DistributionUbuntu&target_version20.04&target_…

DART: Implicit Doppler Tomography for Radar Novel View Synthesis 笔记

Link&#xff1a;https://wiselabcmu.github.io/dart/ Publish&#xff1a; 2024CVPR Abstract DART主要任务就是用来合成雷达距离多普勒图像range-droppler&#xff0c;可用于生成高质量的断层扫描图像。 Related Work 1 Radar Simulation 基于模型的方法 任务&#xff…

XGBoost回归预测 | MATLAB实现XGBoost极限梯度提升树多输入单输出

回归预测 | MATLAB实现XGBoost极限梯度提升树多输入单输出 目录 回归预测 | MATLAB实现XGBoost极限梯度提升树多输入单输出预测效果基本介绍模型描述程序设计参考资料预测效果 基本介绍 XGBoost的全称是eXtreme Gradient Boosting,它是经过优化的分布式梯度提升库,旨在高效、…

医学和生信web APP 平台- Appmatrix

医学&#xff08;和生信&#xff09;web APP 平台- Appmatrix 最近使用shinyproxy将平时所构建的shiny和streamlit医学类应用汇集在一起&#xff0c;实现一站式访问&#xff0c;另外&#xff0c;使用了自己电脑内网穿透&#xff0c;一定程度上缓解了数据分析类APP消耗计算资源…

关闭线程池的API介绍

线程池关闭主要涉及以下几个API: shutdown:关闭线程池&#xff0c;此方法执行后&#xff0c;线程池不会立即关闭&#xff0c;1、等待正在执行的线程任务执行完毕 2、等待任务队列中的任务执行完毕&#xff0c;步骤1和2执行后&#xff0c;线程池才完全中止isShutdown:判断线程池…

PostgreSQL学习笔记六:模式SCHEMA

模式&#xff08;Schema&#xff09; PostgreSQL中的模式&#xff08;Schema&#xff09;是一个命名的数据库对象集合&#xff0c;包括表、视图、索引、数据类型、函数、存储过程和操作符等。模式的主要作用是组织和命名空间数据库对象&#xff0c;使得同一个数据库中可以包含…

C/C++语言基础--C++异常看这一篇就够了

本专栏目的 更新C/C的基础语法&#xff0c;包括C的一些新特性 前言 通过前面几节课&#xff0c;我们学习了抽象、封装、继承、多态等相关的概念&#xff0c;接下来我们将讲解异常&#xff0c;异常是专门处理错误的&#xff1b;这一次加了不少图标&#xff0c;希望大家喜欢;C语…

牛客周赛 Round 63(构造、组合数、线性基)

文章目录 牛客周赛 Round 63(构造、组合数、线性基)A. 小红的好数B. 小红的好数组C. 小红的矩阵行走(简单思维题)D. 小红的行列式构造(构造、数学题)E. 小红的 red 计数(组合数)F. 小红开灯(线性基) 牛客周赛 Round 63(构造、组合数、线性基) A. 小红的好数 按照题意判断即可…

QT事件与网络通信

闹钟 头文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QTimer> #include <QTextToSpeech> // 添加此行以引入QTextToSpeech类QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWin…

Python基础语法条件

注释 注释的作用 通过用自己熟悉的语言&#xff0c;在程序中对某些代码进行标注说明&#xff0c;这就是注释的作用&#xff0c;能够大大增强程序的可读性。 注释的分类及语法 注释分为两类&#xff1a;单行注释 和 多行注释。 单行注释 只能注释一行内容&#xff0c;语法如下…

基于springboot管理系统

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…