【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毫秒的时间,不管是否运行结束都需要替换下去,要么进入运行队列中重新排队,要么进行等待)

相关文章
|
16天前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
3月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
132 1
|
1月前
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
76 34
|
11天前
|
Linux
Linux:守护进程(进程组、会话和守护进程)
守护进程在 Linux 系统中扮演着重要角色,通过后台执行关键任务和服务,确保系统的稳定运行。理解进程组和会话的概念,是正确创建和管理守护进程的基础。使用现代的 `systemd` 或传统的 `init.d` 方法,可以有效地管理守护进程,提升系统的可靠性和可维护性。希望本文能帮助读者深入理解并掌握 Linux 守护进程的相关知识。
27 7
|
10天前
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
32 5
|
10天前
|
Linux 应用服务中间件 nginx
Linux 进程管理基础
Linux 进程是操作系统中运行程序的实例,彼此隔离以确保安全性和稳定性。常用命令查看和管理进程:`ps` 显示当前终端会话相关进程;`ps aux` 和 `ps -ef` 显示所有进程信息;`ps -u username` 查看特定用户进程;`ps -e | grep <进程名>` 查找特定进程;`ps -p <PID>` 查看指定 PID 的进程详情。终止进程可用 `kill <PID>` 或 `pkill <进程名>`,强制终止加 `-9` 选项。
20 3
|
10天前
|
存储 算法 数据处理
进程基础:概念、状态与生命周期
进程是操作系统进行资源分配和调度的基本单位,由程序段、数据段和进程控制块(PCB)组成。线程是进程中更小的执行单元,能独立运行且共享进程资源,具有轻量级和并发性特点。进程状态包括就绪、运行和阻塞,其生命周期分为创建、就绪、运行、阻塞和终止阶段。
50 2
|
1月前
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
67 16
|
2月前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
185 20
|
4月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
580 58