[Linux] 进程管理与调度机制

news2025/1/24 11:39:10

文章目录

  • 一.进程前言
    • 1.冯诺依曼体系结构
    • 2.操作系统
  • 二.进程相关概念
    • 1.PCB
    • 2.查看进程标识符
    • 3.父与子进程
  • 三.进程状态
    • 1.状态类别
      • 1).运行
      • 2).阻塞
      • 3).挂起
    • 2.Linux下的状态
      • 1).R(running)
      • 2).S(Sleeping)
      • 3).D(disk sleeping)
      • 4).T(stopped)
      • 5).t(tracing stopped)
      • 6).Z(僵尸进程)
      • 7).孤儿进程
  • 四.进程优先级
    • 1.查看进程优先级
    • 2.修改进程优先级
  • 五.环境变量
    • 1.相关指令
    • 2.基本的环境变量的理解
    • 3.三个命令行参数
      • 1).int argc
      • 2).char *argv[ ]
      • 3).char *envp[ ]
    • 3.举例测试
  • 六.进程地址空间

一.进程前言

1.冯诺依曼体系结构

请添加图片描述

我们现代的大部分计算机任然遵守着冯诺依曼体系结构(如上图)。
我们去使用软件的时候,数据从输入设备流入我们的存储器(内存),再通过我们的中央处理器进行运算,最终数据从输出设备流出。这是一个典型计算机的工作过程。而了解这些才能更好的理解我们的进程相关概念

2.操作系统

操作系统(OS)是管理计算机硬件与软件资源的系统软件,它为计算机的各个部件提供基础的操作环境和服务。作为计算机硬件和用户之间的桥梁,操作系统负责协调和管理硬件资源,确保各项任务能够高效有序地执行。

如何理解操作系统的沟通功能呢?

请添加图片描述
底层硬件通过中断或直接内存访问将数据传递给操作系统,我们的操作系统将底层硬件的数据和用户输入产生的数据进行整合,
然后统一通过 如链表,等数据结构 进行统一的管理
操作系统的工作就是 接收——描述——整合——管理 的过程

二.进程相关概念

1.PCB

 进程包括程序代码本身,还包含执行程序所需的资源状态信息控制信息。(程序的执行实例)
 每个进程的详细信息被保存在进程控制块(PCB,Process Control Block)。在Linux操作系统下,PCB是task_struct。而task_struct是一个链表的数据结构,可以便于管理进程。
那么操作系统是如何管理和运行我们的进程的呢?
 1.运行一个进程的时候,操作系统会在RAM(内存)上开辟一个空间去存储进程的PCB。
 2.每开一个新的进程就会在这条链表上继续穿插下去

PCB的内容:
1.进程标识符:用来唯一标识一个进程
2.进程状态:就绪,终止,阻塞…
3.程序计数器:保存当下运行的指令
4.寄存器内容(上下文保护):存储寄存器内容,便于下次调度时恢复
5.内存管理信息:记录进程的地址空间信息
6.调度信息:优先级,调度队列的位置(指针),时间片…
7.I/O状态:该进程是否正在I/O输入或输出。
8.文件管理信息:打开的文件列表以及相应的访问权限和操作。
9.父进程和子进程信息:每个进程都有父进程,或者有子进程。
10.信号信息:操作系统会使用信号来通知进程某些事件的发生(如终止、暂停等)
11.时间信息:程序运行的时间等等。
12.进程通信信息:进程间通信(IPC)相关的信息,如管道、消息队列、共享内存等的状态,记录进程间如何交换数据。
加深了我们对“Linux下一切皆文件”的理解

2.查看进程标识符

我们可以在Linux下的/proc文件夹查看我们进程相关的信息。
而文件夹的 ID 就是PCB下的唯一标识符。
请添加图片描述
也可以通过ps(process status)指令来查看我们的进程

指令作用
-e显示系统中的所有进程(包括其他用户的进程)
-A与 -e 类似,但更为全面,显示所有进程
-ef使用“全格式”输出,显示更多详细信息,如父进程 PID(PPID)、启动时间等。
-u显示特定用户的进程,可以替换 username 为具体的用户名。
-aux显示所有用户的进程(不仅是当前用户的进程)。进程的用户/所有者,没有控制终端的进程(例如守护进程)。

在这里插入图片描述
在这个进程列表之中,PPID和PID分别代表父进程ID和自己的进程ID。

3.父与子进程

在Linux下一个进程是可以创建另一个子进程的
 创建者就是父进程,被创建者就是子进程。
初始fork(),:
 fork是一个系统调用接口,可以创建一个子进程。
他有两个返回值!!!
在父亲进程中返回子进程ID
在子进程中返回0
eg:

  1 #include <iostream>
  2 #include <unistd.h>
  3 using namespace std;
  4 int main()
  5 {
  6   pid_t id = fork();
  7   if(id==0)
  8   {
  9     while(1)
 10     {
 11       cout<<"我是子 ID:"<< getpid()<<"我的ppid:"<<getppid()<<endl;
 12       sleep(1);
 13     }
 14   }
 15   else
 16   {
 17     while(1)
 18     {
 19        cout<<"我是父 ID:"<<getpid()<<"我的ppid:"<<getppid()<<endl;                                                                              
 20        sleep(2);
 21     }
 22   }
 23		return 0;
 24 }

在这里插入图片描述

三.进程状态

1.状态类别

状态共有
1.就绪 2.运行 3.阻塞 4.挂起 5.终止
就绪与运行十分相似
这边着重区分运行,阻塞,挂起。

1).运行

  运行状态不仅是当前CPU调度的进程的状态,运行队列中的的进程都是运行状态。
从操作系统知道,操作系统对进程的管理是通过链表task_struct进行的。而我们的CPU只有单核或多核(远远小于进程的数量),那么操作系统可以通过何种方式使得进程可以流畅的运行呢?
  运行队列就可以做到,操作系统创建一个运行队列,将进程的PCB通过链表连接起来,再设定一个时间片,每一个进程在时间片规定的时间内完成相应的工作,超出时间片就将CPU等各种资源交给下一个进程,如此往复(因为时间片的时间非常的短,所以我们肉眼感受不到进程的切换)请添加图片描述

2).阻塞

   CPU访问内存的速度是要远远快于外存的
  当进程访问我们的外设进行I/O(输入/输出)时我们的运行队列该如何处理呢?总不能等着进程I/O浪费资源吧,所以操作系统衍生了阻塞这一状态,它可以将当前正在I/O的进程移出运行队列,并移入我们的等待队列(wait_list),CPU释放I/O指令给外设,使我们的进程在等待队列中排队,等到该外设空闲时进行I/O,I/O结束后又回到我们的运行队列中来。请添加图片描述

3).挂起

   PCB是一直存放在我们的内存上的,如果我们阻塞的进程很多很多,PCB是否会过多的占用内存空间呢?是的!
  所以操作系统有衍生了挂起状态(它是操作系统为节省内存资源而采取的特殊状态),当进程还未调用资源的时候,为了防止PCB过多的占用内存
操作系统会将PCB暂时存放在硬盘上,这样等轮到该进程调度资源的时候,再将其加载到内存上去。节省空间。有两种情况会引起挂起的出现:
1.阻塞状态
2.就绪状态(PCB刚加载好就被挂起)
请添加图片描述

2.Linux下的状态

Linux下的状态又有细微的差别,在Linux源码下对于进程的状态有如下的定义

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 */
};

+号代表前台程序

1).R(running)

  与运行状态相同

  1 #include <iostream>
  2 int main()
  3 {
  4   while(1)
  5   {
  6                                                                                                                                                 
  7   }
  8   return 0;
  9 } 

在这里插入图片描述

2).S(Sleeping)

  与阻塞状态相似

  1 #include <iostream>
  2 #include <unistd.h>
  3 using namespace std;
  4 int main()
  5 {
  6   while(1)
  7   {
  8     cout<<"我在打印,对硬件进行I/O"<<endl;
  9     sleep(1);                                                                                                                                   
 10   }
 11   return 0;
 12 }

请添加图片描述

3).D(disk sleeping)

  深度睡眠状态,在Linux下我们通过操作系统可以杀掉一个进程。如果我的进程正在进行高强度的I/O呢,这时杀掉进程就会导致数据损坏或者传输失败,这不会是我们想要看到的,所以Linux使用了D状态,他表示进程进入了深度睡眠,无法被操作系统通过常规手段杀掉。

这里能力不足,无法演示qwq…

4).T(stopped)

  stopped 状态表示进程被信号暂停了执行,此时进程不占用 CPU 资源,也不会继续执行任何指令。
下面是kill指令,用来强制暂停进程
请添加图片描述
在这里插入图片描述
  通过kill -19 2433 暂停进程
请添加图片描述
  此时如果我们使用kill -18 2433 continue进程就会导致进程从前台程序变为后台程序,且无法被 Ctrl + C 杀掉,只能通过 kill -9 杀掉进程。

5).t(tracing stopped)

  Tracing stop 状态是 Linux 中 stopped 状态的一个特例。它表示进程被父进程(通常是调试器或跟踪工具)通过 ptrace 系统调用暂停,用于调试或分析进程的行为。
如我们使用gdb,就会触发可追踪的暂停。以便调试在这里插入图片描述
t状态如下:

请添加图片描述

6).Z(僵尸进程)

  进程可以创建子进程,那如果子进程被杀掉了,会发生什么呢?
系统并不会回收子进程的资源,因为子进程是由其父进程管理的,父进程如果一直不收回的话,该子进程就变为了僵尸进程。不会被收回!!!,一直占用空间。请添加图片描述

7).孤儿进程

  如果父进程被杀掉了呢,此时子进程又将何去何从。
父进程死亡后,子进程便会被PID=1的init进程领养,便于管理和避免出现僵尸进程。

四.进程优先级

CPU资源分配的优先顺序,便是进程的优先级。

1.查看进程优先级

请添加图片描述
linux下进程的优先级由 PRI(priority)和NI(nice) 共同表示。
PRI是实际优先级
NI是优先级的偏移量 (-20~19)
值越小优先级越高
PRI=基础优先级+NI

为什么Linux下设定PRI初始为80呢?
  实际上在Linux下,PRI的值映射范围是0 ~ 139,其中(0 ~ 99为实时优先级,100 ~ 139为普通优先级)而设定初始的 PRI值和NI值 的目的就是为了使操作系统能够更好的管理进程的优先级,80为平衡值使有些系统级的进程能更优的分配优先级。

2.修改进程优先级

top

指令可以查看和修改优先级
sudo top -> r ->输入PID ->输入NI值
即可修改,结果如下

请添加图片描述

五.环境变量

  环境变量 是操作系统中用于存储配置信息的一种变量。
  环境变量就好比是操作系统的全局变量,它们为操作系统和应用程序提供重要的配置信息。
如:我们在编译C++/C语言程序的时候,编译器是如何知道动静态库的位置的呢?通过操作系统的环境变量即可,锁定动静态库的路径。

1.相关指令

  1.使用echo指令以查询环境变量

echo $PATH
echo $USER
echo $HOME
......

  2.使用env指令查询全部环境变量

env

  3.export指令添加环境变量

export MY_VAR="Hello, World!"

2.基本的环境变量的理解

1.PATH
  为什么有些方法可以直接使用,而 可执行程序 要带上路径才能使用呢
  因为PATH环境变量,当我们直接输入指令的时候,shell会在PATH路径下搜索相应的可执行程序。
测试:
在这里插入图片描述
效果如下:(可以不用带路径了)重启电脑环境变量会自动恢复为初始状态
在这里插入图片描述
2.HOME
  cd ~指令为什么可以直接使用?他是如何知道我的位置的?
  cd ~指令直接访问了HOME,知晓家目录路径。
3.USER
  有些指令我们无法通过普通用户去使用访问,这是因为他会检测USER是否为“root”。
  但是通过sudo指令,可以短暂提权。他并不会修改USER的值。
。。。。。。

3.三个命令行参数

int main(int argc,char* argv[],char* envp[])
{
	return 0;
}

以上的3个命令行参数应该并不少见

1).int argc

表示命令行参数的个数(argument count)
以ls指令为例

ls -a -l

  我们知道linux是由C语言编写的,所以ls其实也是个C语言可执行程序
后面紧跟 -a -l 作为命令行参数
ls -a -l 的个数为2,故argc==2

2).char *argv[ ]

表示命令行参数的值(argument vector)
   同理,argv这个指针数组存放的就是“-a” “-l”的指令,我们可以通过前两个参数来为我们的C/C++程序制定功能。

3).char *envp[ ]

表示环境变量(environment pointer)
  char*envp[ ]会将环境变量传入,我们可以通过环境变量进行不同功能的划分。
  envp可以不传输,因为每一个程序都会获得一张环境表char * environ,可以直接通过访问该表来读取环境变量的值。

3.举例测试

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char* argv[])
{
  if(argc!=0)
  {
    int x;
    for(x=0;x<argc;x++)
    {
      if(strcmp(argv[x],"-a")==0)
      {
        printf("执行-a指令\n查询用户类型\n");
        char*who=NULL;
        who=getenv("USER");//可以直接通过getenv来获取                                                                                       
        if(strcmp(who,"root")==0)
        {
          printf("我是root\n");
        }
         else{     
	  printf("我是用户\n");                                                                                                                 
        }
         return 0;
      }
    }
  }
  
  printf("无法分析指令\n");
  return 0;
}

在这里插入图片描述

六.进程地址空间

   对于一个进程而言,进程地址空间实际上是一个虚拟内存空间,其中在Linux下操作系统通过mm_struct对进程的地址空间的每个区域进行划分,如:代码段,已初始化数据区域,未初始化数据区域,栈区,堆区…
   虚拟地址通过页表物理地址形成映射。这样在运行进程的时候,CPU可以直接访问物理地址,虚拟地址可以对进程起到约束的作用,防止其访问其它物理内存。并且可以使不连续的物理内存变得逻辑连续。并且保证了进程独立性。
  但是程序在编译的时候就已经有地址出现了,这是为何呢?
  虚拟内存的规则不仅仅操作系统遵守,编译器也会遵守。当编译一个程序时,程序内部的函数地址,变量地址…都会有一个虚拟地址,当运行程序时,操作系统直接把该进程的代码放入代码段区域。CPU读取代码段的虚拟地址(函数地址,变量地址…),并直接通过页表对物理内存进行映射,CPU是无法看到物理地址的,他永远通过虚拟地址访问。
上述结构大致如下:
请添加图片描述

这里还有一个代码帮助理解。
eg:

int main()
{
  int global = 100;
  pid_t id=fork();
  if(id==0)
  {
    while(1)
    {
      printf("我是子 :global=%d,&global=%p\n",global,&global);
      sleep(1);
    }
  }
  else{
    int cnt=0;
    while(1)
    {
      printf("我是爹 :global=%d,&global=%p\n",global,&global);
      sleep(1);
      cnt++;
      if(cnt==3)
      {
        global=900;
        printf("我是爹,global已被更改%d\n",global);
      }
    }
  }

  return 0;
}

请添加图片描述
   为什么两个进程的全局变量地址相同但是全局变量的值不同呢,Linux下有一种功能叫做写时拷贝,当父进程新建子进程的时候,子进程会继承父进程的代码,并且还在同一个物理地址上,但是如果父进程或者子进程如果对其中的某一内存页进行修改时,就会触发写时拷贝,系统会新开一块区域交由子进程。

创作不易,恳请留赞,互三互三

在这里插入图片描述

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

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

相关文章

复位信号的同步与释放(同步复位、异步复位、异步复位同步释放)

文章目录 背景前言一、复位信号的同步与释放1.1 同步复位1.1.1 综述1.1.2 优缺点 1.2 recovery time和removal time1.3 异步复位1.3.1 综述1.3.2 优缺点 1.4 同步复位 与 异步复位1.5 异步复位、同步释放1.5.1 总述1.5.2 机理1.5.3 复位网络 二、思考与补充2.1 复…

Unity中关于实现 管道水流+瀑布流动+大肠蠕动效果笔记

Unity中关于实现 管道水流瀑布流动大肠蠕动效果笔记 效果展示&#xff1a; 参考资料及链接&#xff1a; 1、如何在 Unity 中创建水效果 - 水弯曲教程 https://www.youtube.com/watch?v3CcWus6d_B8 关于补充个人技能中&#xff1a;顶点噪波影响网格着色器配合粒子实现水特效 …

Cloudpods是一个开源的Golang实现的云原生的融合多云/混合云的云平台,也就是一个“云上之云”。

Cloudpods是一个开源的Golang实现的云原生的融合多云/混合云的云平台&#xff0c;也就是一个“云上之云”。Cloudpods不仅可以管理本地的虚拟机和物理机资源&#xff0c;还可以管理多个云平台和云账号。Cloudpods隐藏了这些异构基础设施资源的数据模型和API的差异&#xff0c;对…

【LeetCode】--- MySQL刷题集合

1.组合两个表&#xff08;外连接&#xff09; select p.firstName,p.lastName,a.city,a.state from Person p left join Address a on p.personId a.personId; 以左边表为基准&#xff0c;去连接右边的表。取两表的交集和左表的全集 2.第二高的薪水 &#xff08;子查询、if…

JavaScript学习笔记(3)

一.BOM对象 BOM的全称是Browser Object Model,翻译过来是浏览器对象模型。也就 是JavaScript将浏览器的各个组成部分封装成了对象。我们要操作浏览器的部分功能&#xff0c;可以通过操作 BOM对象的相关属性或者函数来完成。例如&#xff1a;我们想要将浏览器的地址改为 http:/…

DRG/DIP 2.0时代下基于PostgreSQL的成本管理实践与探索(下)

五、数据处理与 ETL 流程编程实现 5.1 数据抽取与转换(ETL) 在 DRG/DIP 2.0 时代的医院成本管理中,数据抽取与转换(ETL)是将医院各个业务系统中的原始数据转化为可供成本管理分析使用的关键环节。这一过程涉及从医院 HIS 系统中抽取患者诊疗数据,并对其进行格式转换、字…

【玩转全栈】----YOLO8训练自己的模型并应用

继上篇&#xff1a; 【玩转全栈】---基于YOLO8的图片、视频目标检测-CSDN博客 相信大家已经可以训练一些图片和视频了&#xff0c;接下来我将为大家介绍如何训练自己的特定模型&#xff0c;并用其进行检测 目录 准备数据 图片数据 标识数据 配置文件 运行 测试训练结果 存在的问…

简洁实用的wordpress外贸模板

简洁、实用、大气的wordpress外贸模板&#xff0c;适合跨境电商搭建外贸B2B产品展示型网站。 简洁实用的wordpress外贸模板 - 简站WordPress主题简洁、实用、大气的wordpress外贸模板&#xff0c;适合跨境电商搭建外贸B2B产品展示型网站。https://www.jianzhanpress.com/?p828…

Caesar

Caesar 打开.txt: oknqdbqmoq{kag_tmhq_xqmdzqp_omqemd_qzodkbfuaz} 根据题目判断是凯撒密码&#xff0c;flag前头是cyberpeace{}&#xff0c;可以得到偏移量是12. 所以&#xff1a; cyberpeace{you_have_learned_caesar_encryption} 下面是我找的关于凯撒密码的解密脚本 c…

OpenEuler学习笔记(四):OpenEuler与CentOS的区别在那里?

OpenEuler与CentOS的对比 一、基本信息 起源与背景&#xff1a; OpenEuler&#xff1a;由华为发起&#xff0c;后捐赠给开放原子开源基金会&#xff0c;旨在构建一个开放、多元化的云计算和边缘计算平台&#xff0c;以满足华为及其他企业的硬件和软件需求。CentOS&#xff1a;…

纯css实现div宽度可调整

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>纯css实现div尺寸可调整</title><style…

Cesium特效——城市白模的科技动效的各种效果

最终效果图如下&#xff1a; 实现方法&#xff1a; 步骤一&#xff1a;使用cesiumlib生产白模&#xff0c;格式为3dtiles 注意事项&#xff1a;采用其他方式可能导致白模贴地&#xff0c;从而导致不能实现该效果&#xff0c;例如把步骤二的服务地址改为Cesium Sandcastle 里的…

JavaWeb 学习笔记 XML 和 Json 篇 | 020

今日推荐语 愿你遇见好天气,愿你的征途铺满了星星——圣埃克苏佩里 日期 学习内容 打卡编号2025年01月23日JavaWeb笔记 XML 和 Json 篇020 前言 哈喽&#xff0c;我是菜鸟阿康。 以下是我的学习笔记&#xff0c;既做打卡也做分享&#xff0c;希望对你也有所帮助…

【力扣:新动计划,编程入门 —— 题解 ②】

—— 25.1.23 1512. 好数对的数目 给你一个整数数组 nums 。 如果一组数字 (i,j) 满足 nums[i] nums[j] 且 i < j &#xff0c;就可以认为这是一组 好数对 。 返回好数对的数目。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,1,1,3] 输出&#xff1a;4 解释&#xff…

如何在data.table中处理缺失值

&#x1f4ca;&#x1f4bb;【R语言进阶】轻松搞定缺失值&#xff0c;让数据清洗更高效&#xff01; &#x1f44b; 大家好呀&#xff01;今天我要和大家分享一个超实用的R语言技巧——如何在data.table中处理缺失值&#xff0c;并且提供了一个自定义函数calculate_missing_va…

《RWA全球产业白皮书》发布:向凌云教授解析全球经济转型与RWA的未来

2025年1月16日&#xff0c;旅美经济学家、全球新兴产业金融专家向凌云教授在美国发布了引人注目的《RWA全球产业白皮书》。该白皮书通过深入分析全球产业结构变化&#xff0c;尤其强调了“真实世界资产”&#xff08;Real-World Assets&#xff0c;简称RWA&#xff09;在当前及…

TOGAF之架构标准规范-信息系统架构 | 数据架构

TOGAF是工业级的企业架构标准规范&#xff0c;信息系统架构阶段是由数据架构阶段以及应用架构阶段构成&#xff0c;本文主要描述信息系统架构阶段中的数据架构阶段。 如上所示&#xff0c;信息系统架构&#xff08;Information Systems Architectures&#xff09;在TOGAF标准规…

安宝特方案 | AR在供应链管理中的应用:提升效率与透明度

随着全球化的不断深入和市场需求的快速变化&#xff0c;企业对供应链管理的要求也日益提高。如何在复杂的供应链环境中提升效率、降低成本&#xff0c;并确保信息的透明度&#xff0c;成为了各大行业亟待解决的问题。而增强现实&#xff08;AR&#xff09;技术&#xff0c;特别…

C语言数组详解:从基础到进阶的全面解析

在C语言中&#xff0c;数组是一种基本的数据结构&#xff0c;用于存储多个相同类型的数据。数组的引入使得C语言能够高效地存储和操作大量数据。在任何一个C语言程序中&#xff0c;数组都发挥着极其重要的作用。无论是在算法实现、数据存储、还是在复杂程序的设计中&#xff0c…

阴沟翻船题——Longest Substring Without Repeating Characters

一、事件概述 今天接到一个面试&#xff0c;让线上做题。面试官出了个leetcode的题。题目如图所示&#xff1a; 我没有刷过leetcode&#xff0c;上学时候我们做的hdu-acm和codeforces。咋一接到题目&#xff0c;看到是个字符串题&#xff0c;并且找最长字串&#xff0c;第一反…