【Linux】7. 进程概念

简介: 【Linux】7. 进程概念

在进程的学习之前首先需要理解并掌握冯诺依曼体系结构及操作系统的相关概念

1. 冯诺依曼体系结构

在这里插入图片描述
在这里插入图片描述
最终我们得到的结论是:
在数据层面上

  1. CPU不与外部设备进行交互,而是直接和内存交互
  2. 所有的外部设备需要数据载入,只能载入到内存中。数据从内存中写出,也一定是需要写到外部设备当中

==程序需要运行就必须加载到内存当中,为什么呢?
因为冯诺依曼体系结构规定CPU需要执行我的代码/访问我的数据就只能从内存中读取==

在这里插入图片描述

2. 操作系统

在这里插入图片描述
在这里插入图片描述
经过上面的描述,我们清楚的知道了管理的本质是对数据进行管理,管理方法是先描述再组织,但是以上都是操作系统管理硬件的方式,那么操作系统是如何管理软件的呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 进程概念

在这里插入图片描述

4. 进程指令

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
==命令行上启动的进程,一般情况下(不是特殊情况)它的父进程都是bash!==

5. fork 创建子进程

在这里插入图片描述

6. 进程状态

6.1 为什么要存在进程状态

在这里插入图片描述

6.2 R- 运行状态

在这里插入图片描述

6.3 阻塞状态

假设CPU在执行处于运行状态的某个进程时(该进程处于运行队列当中),发现该进程要往磁盘上写入数据(fwrite),但是CPU的运行效率和磁盘相比不是一个量级的,CPU并不想等待磁盘做出响应(太慢),所以CPU将该进程从运行队列中拿出,将该进程链入磁盘的等待队列当中,CPU继续调度运行队列中的其他进程。
==对于CPU来讲,CPU永远执行的是处于运行状态的进程,一旦该进程需要访问外设资源时,CPU就会将其从运行队列中拿出,链入到对应外设的等待队列当中==
当该进程处于外设的等待队列中时,该进程也就不是R状态,我们将此时的进程状态称之为阻塞状态。
而上述的挪动操作并不是将加载到内存的代码和数据进行挪动而是针对进程的task_struct(PCB)对象放入到不同的队列当中。

当磁盘准备完毕(可以写入的状态)时,操作系统读取到磁盘当前的状态,发现磁盘的等待队列中存在进程,将该进程改为R状态,并重新放入到运行队列当中。

所谓的进程的不同状态,本质是进程(PCB)处于不同的队列当中,等待某种资源(位于运行队列当中就是在等待CPU资源,位于外设队列当中就是在等待外设资源)

6.4 挂起状态

假设当前内存中存在3个进程需要等待磁盘资源才能运行,也就是这三个PCB都处于阻塞状态在等待磁盘资源的到来,当磁盘资源准备完毕后这3个进程会不会被立即调度呢?
答案是不会,操作系统会先将这三个进程的阻塞状态改为R状态,进入到运行队列当中等待CPU调度
但是这种等待外设资源的进程可能需要等待很长时间,而在等待期间,该进程不会被调度,而其代码和数据又会在内存中占用空间,如果内存出现内存不够的情况下该如何处理呢?
将该进程的代码和数据暂时保存到磁盘当中(就节省了内存的空间),这部分省下的空间可以给操作系统使用
这种策略是针对所有进程的,并不是只针对几个

我们把这种将进程的代码和数据暂时保存到磁盘上的现象称之为进程被挂起了
挂起并不代表释放,该进程的内核数据结构(PCB)还存在于内存当中,当该进程要调度时,再将其代码和数据载入到内存当中,将该进程的状态改为R,再放入运行队列当中最后再运行。
将进程的相关数据加载或保存到磁盘当中,称为内存数据的换入换出

6.5 阻塞 vs 挂起

==阻塞不一定挂起,但是挂起一定阻塞==

7. Linux下的状态

上述的进程状态都是在宏观操作系统的角度来看待的,接下来我们来看看Linux操作系统下时如何实现这些进程状态

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
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 */
};

该数组中保存的就是Linux下的进程状态信息

'R'状态 -- 运行状态

在这里插入图片描述

'S'状态 -- 休眠状态

在这里插入图片描述
S状态对应的就是操作系统中阻塞状态的一种

'T'状态 -- 暂停状态

在这里插入图片描述
当前进程处于暂停状态,暂停状态属于阻塞的一种,该进程可以被挂起。
对于用户而言,该进程代码没有被执行,被暂停了。至于是否被挂起,则是由操作系统决定的
在这里插入图片描述
经过上述学习,T暂停状态和S休眠状态都是阻塞状态中的一种,至于是否挂起都是取决于操作系统,而操作系统认为挂起状态并不需要暴露给用户,用户只需要关系进程当前是什么状态即可!

'D' 状态 -- 深度睡眠

'S'状态 被称为浅度睡眠状态,该状态的进程可以被终止
而处于'D'状态深度睡眠的进程无法被终止
在通常使用操作系统时,都不会出现该状态,一般出现在数据库的开发"高IO/高并发"的场景当中

现在来模拟该场景:
假设操作系统中存在进程A 包含10万条用户数据写入到磁盘当中,当进程A被加载到内存当中时,进程A需要访问磁盘资源并写入,磁盘在写入时,进程A等待磁盘写完并返回....
假设此时操作系统资源吃紧,操作系统采用挂起进程的策略将内存中的空间腾出来,但是还是无法解决问题,此时操作系统发现了游手好闲的进程A(啥事不干) 且当前操作系统资源紧缺,Linux操作系统就将进程A杀死了(不杀自己就要死了)......
此时磁盘将数据写完,发现写入的过程中出现部分失败的数据,要告诉进程A相关信息,但是此时进程A已经被杀死了,没有进程接收退出信息。数据就被丢失....
此时用户前来了,需要写入的数据被丢失,当前数据非常重要该问责谁呢?
那么此时用户就给操作系统下规定:凡是需要往磁盘写入重要数据的进程,给个免死金牌'D'状态,无法再被操作系统杀死,只能通过断电或者进程自己醒来解决(只有高IO时,才能看见D状态)

't' 状态 -- 被追踪

在这里插入图片描述

'X'状态 -- 死亡

'X'状态表示的是死亡状态,这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
在Linux操作系统当中无法验证,因一旦进程死亡,操作系统会立即或者延时(相较于CPU而言,非常快)将其所占用资源回收(PCB,代码在内存所在空间等),所以无法查看

'Z'状态 -- 僵尸

僵死状态(Zombies)是一个比较特殊的状态。
当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
在这里插入图片描述

僵尸进程的危害

进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,也就意味着子进程就一直处于Z状态!!!
维护退出状态本身就是需要数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护
==那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?==
是的!因为数据结构对象本身就要占用内存,PCB需要一直维护处于僵尸状态的进程(而且该进程无法使用kill命令杀死,因为进程已经退出了,无法响应)属于"占着茅坑不拉屎"(占用内存资源)
==那么是否会造成内存泄漏呢?== 会的!

7. 孤儿进程

在这里插入图片描述
在这里插入图片描述

8. 进程优先级

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9. 进程切换

10. 其他概念

竞争性:

系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
举例:学生在食堂打饭是需要排队(进程在运行时的运行队列,根据优先级进行排队执行)

独立性:

多进程运行,需要独享各种资源,多进程运行期间互不干扰
举例:我们在使用手机(Linux操作系统)时,迅雷下载中止会影响QQ运行嘛?/ 打游戏闪退会导致抖音也闪退嘛?
很明显不会,所以进程是具有独立性的
==我们已经知道不相干的进程具有独立性,那么对于父子进程呢?==
在这里插入图片描述

并行:

多个进程在多个CPU下分别,同时进行运行,这称之为并行
存在多个CPU,可以使得在同一时刻可以有多个进程分别在各个CPU上运行,称之为并行

并发:

多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
如果只有1个CPU,那么在同一时刻只能存在1个进程在运行
但是我们都知道,进程并不是运行起来就独占CPU资源直到结束的,而是时间片轮转的策略
(比如:获得CPU资源后,只能使用10毫秒的时间,不管是否运行结束都需要替换下去,要么进入运行队列中重新排队,要么进行等待)

相关文章
|
25天前
|
NoSQL Linux 编译器
GDB符号表概念和在Linux下获取符号表的方法
通过掌握这些关于GDB符号表的知识,你可以更好地管理和理解你的程序,希望这些知识可以帮助你更有效地进行调试工作。
77 16
|
1月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
67 16
|
2月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
176 67
|
1月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
64 20
|
17天前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
|
16天前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
|
17天前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
|
17天前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
|
3月前
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
3月前
|
存储 Linux 调度
【Linux】进程概念和进程状态
本文详细介绍了Linux系统中进程的核心概念与管理机制。从进程的定义出发,阐述了其作为操作系统资源管理的基本单位的重要性,并深入解析了task_struct结构体的内容及其在进程管理中的作用。同时,文章讲解了进程的基本操作(如获取PID、查看进程信息等)、父进程与子进程的关系(重点分析fork函数)、以及进程的三种主要状态(运行、阻塞、挂起)。此外,还探讨了Linux特有的进程状态表示和孤儿进程的处理方式。通过学习这些内容,读者可以更好地理解Linux进程的运行原理并优化系统性能。
132 4