当前位置: 首页 > news >正文

Linux进程概念(1)

本次,我们讲解的是关于Linux的进程的基础概念认识:

首先,我们先从硬件层面谈起:得先了解一个计算机体系结构:

 冯诺依曼体系结构:

一、硬件组成


(一)中央处理器(CPU) 组件
- 运算器:执行数据的算术运算(如加减乘除)和逻辑运算(如与或非)。
- 控制器:对计算机硬件部件进行控制,协调各组件工作。
(二)外设
- 输入设备:向计算机输入数据,如鼠标、键盘、摄像头、话筒、磁盘、网卡等。
- 输出设备:将计算机处理结果输出,如显示器、播放硬件、磁盘、网卡等;部分设备兼具输入输出功能。
- 存储器:这里指内存,是硬件级的缓存空间,处于核心地位。
二、工作原理
程序运行时,必须先加载到内存中执行,这是冯·诺依曼体系结构的规定。
三、组件连接
各个硬件单元通过“总线”链接,主要包括系统总线和 I/O 总线。
四、存储分级(存储金字塔)


从上层到下层,价格越来越低、容量越来越大、速度越来越慢、离CPU越来越远,层级如下:

(注:这种分级设计平衡了存储的速度、容量与成本。)

ps:这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)

外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取
总结:所有设备都只能直接和内存打交道

举个例子:

微信聊天,整个数据流是怎么流动的?

输入设备:键盘,网卡,磁盘.......

输出设备:显示器......

ps:了解完了冯诺依曼体系的原理后,我们再回过头来想想,上次我们写的进度条,默认显示的数据,是可能会缓存起来的,在哪里保存呢?就是在存储器。

谈完硬件层面后,现在,我们来谈一下关于软件层面的:

二、软件层面



一、操作系统

是什么?

操作系统是一款进行管理(对硬件,软件)的软件。

为什么?

1. 资源管理:帮助用户管理好计算机的软硬件资源。

操作系统通过管理底层的软硬件资源(手段),

为用户(使用者,程序员)提供一个良好的执行环境(目的)。
2. 环境提供:为用户提供稳定、高效、安全的运行环境。

操作系统的数据安全与接口

- 操作系统内部包含各种数据,但它不信任任何用户。
- 为保证自身数据安全并为用户提供服务,操作系统以接口的方式给用户提供调用入口,使用户能获取其内部数据。----(这个接口就是系统调用接口)(看上面的图片)

系统调用 

- 是操作系统提供的用C实现的内部函数调用。
- 所有访问操作系统的行为,都只能通过系统调用来完成。

操作系统是一个进行管理的软件,那么它是怎么管理的呢?

管理的核心逻辑(如何管理)

先描述再组织

例子背景:一个学校那么多学生,学校领导是如何进行管理的?(简单版本)

需要的人物:

校长(决策者)->操作系统,

辅导员(执行者)-->驱动程序,

学生(被管理者)-->软硬件资源

(层层向上提供信息)


一、“描述-组织”的管理实现路径

以学生管理为例,展现“先描述,再组织”的过程:

- 描述过程:用结构体(如  struct student )定义学生的属性(学院、专业、班级、姓名、性别、身高、体重、籍贯、电话等),将“学生”这一管理对象数据化。

- 组织过程:通过数据结构(如链表,借助  struct student *next  实现节点连接)将多个学生的信息组织起来,从而把对学生的管理”转化为对链表(数据结构)的增删改查

类似地,其他管理对象也可通过结构体(如  struct person  描述个人信息, struct contact  组织多人联系信息)实现“数据化-结构化”的管理。

二、管理的核心逻辑

从上面知道,管理者与被管理者是不需要见面的,管理者在不见被管理者的情况下,如何做好的管理呢?只要能够得到管理信息,就可以在未来进行管理决策,
-->管理的本质:是通过对数据的管理,达到对人的管理。

-->管理者和被管理者面都不见,那么我们怎么拿到对应的数据的?是通过执行者拿到的

eg(学校例子中的辅导员)

三、操作系统中的管理映射

在操作系统场景中,任何管理对象最终都可转化为对某种数据结构的增删改查。程序员开发软件时,需通过操作系统提供的接口(系统调用)来访问其内部数据结构,所有对操作系统的操作都依赖系统调用完成。

总结:

1. 管理者和被管理者可以不见面,只要能拿到管理信息,就可在未来进行管理决策。
2. 管理的本质是通过对数据的管理,达到对人的管理。
3. 管理者和被管理者表面不见时,可通过执行者来实现对应的数据操作。

因此:管理的核心六大字!!!!!

先描述再组织

再谈进程1

ps:现在只是简单版本的认识,等到后面学着学着会逐渐补充完善的。

有了上面的铺垫后,我们现在来了解一下关于进程的知识点。

是什么

- 一个已加载到内存中的程序,称为进程,也可理解为“任务”。
- 正在运行的程序,也叫进程。

二、进程的组成

进程 = 内核PCB数据结构对象 + 自身的代码和数据。(目前简单理解,其实还不算很准确)
**PCB(Process Control Block,进程控制块),Linux操作系统的PCB是task_struct

**是描述进程所有属性的结构体对象,包含进程编号、状态、优先级、相关指针信息(如  struct PCB *next  用于链表组织)等属性集合。

三、操作系统对进程的管理逻辑

- 操作系统不仅可以运行一个还可同时运行多个进程,因此必须对进程进行管理,

怎么管理?**“先描述,再组织”**。
- 描述:进程加载到内存时,操作系统会先创建对应的PCB结构体对象,用其属性描述进程。
- 组织:通过PCB中的指针将多个进程组织成单链表(或其他数据结构),对进程的管理最终转化为对该链表的增删改查操作。



四、认知逻辑延伸 

- 人们认知事物(包括进程)的方式,是通过属性的集合来识别;当属性足够丰富时,这些属性的组合就标识了具体对象(如进程的PCB属性集合标识了一个进程)。

五、看Linux下进程是如何做的?

在Linux中描述进程的结构体叫做task_struct。

task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息

Linux中是如何组织进程的,Linux内核中,最基本的组织进程task_struct的方式,采用双向链表组织的。

它的内容:

标示符: 描述本进程的唯一标示符,用来区别其他进程。

状态: 任务状态,退出代码,退出信号等。

优先级: 相对于其他进程的优先级。

程序计数器: 程序中即将被执行的下一条指令的地址。

内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针

上下文数据: 进程执行时处理器的寄存器中的数据。

I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。

记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

其他信息

查看进程:

ps axj 查看所有进程
指令:
ls /proc/

指令:
top

指令:
ps aux | grep test |grep -v grep

ps:指令怎么知道进程在哪?

五、理解指令与进程的关系

在Linux系统中,用户输入的指令(如pwdlsgrep)本质上是可执行程序或内置命令。当这些指令被执行时,操作系统会为其创建独立的进程

pwdls这类指令的进程生命周期非常短暂,执行完成后立即终止。它们的输出通常是静态信息(如当前目录或文件列表),不会涉及复杂的系统状态遍历。

六、grep进程的特殊性

grep是一个用于文本搜索的工具,其工作原理是逐行扫描输入并匹配关键字。当执行grep命令时:

  • 操作系统为其创建新进程。
  • 该进程会加载grep的代码到内存,并开始执行搜索逻辑。

七、自包含过滤问题

当使用grep过滤包含自身关键字的进程时(例如ps aux | grep test),可能出现以下现象:

  1. grep test本身是一个进程,其命令行参数包含关键字test
  2. ps aux会列出所有进程信息,包括grep test这个进程。
  3. 因此过滤结果会包含grep进程自身。
指令:ls /proc/(进程编号) -l

查看进程指令(常用)

ps ajx | head -1 && ps ajx |grep test |grep -v grepps ajx | head -1  展示它的名称,方便我们看它对应的数是属于哪一个
&&   并且,一起执行的意思
ps ajx |grep test |grep -v grep  打印出来进程,并过滤一下

系统调用来获取标识符

getpid:获取进程ID,即PID

getppid:获取父进程ID,即PPID

系统调用来创建进程:

fork()

我们可以在Linux下,man查一下。

tips:进去后,/return val (想追踪的信息,如果存在的话,都可以直接定位到该位置)

话不多说,先来段代码来初识一下:

看上面的图片,我们可能会又以下疑问:

问题:

1.为什么fork要给子进程返回0,给父进程返回子进程的pid

2.一个函数是如何做到返回两次的?如何理解?

3.一个变量怎么会有不同内容,如何理解?

接下来,我们就会围绕上面三个问题展开来讲:

一、 fork()  核心行为

fork()  是 Linux 系统调用,用于创建子进程。它会复制父进程的内核数据结构(如  task_struct ,包含  pid 、 ppid  等标识)以及代码等资源,生成与父进程几乎一致的子进程。之后,父、子进程会从  fork()  调用后的代码行开始,各自独立执行。

ps:进程=内核数据结构+代码和数据

进程中的数据是通过写时拷贝来实现的。 

所以,我们就可以回答:

1.为什么fork要给子进程返回0,给父进程返回子进程的pid?

为了让父和子执行不同的事情!需要想办法让父和子进程执行不同的代码块。从而让fork具有了不同的返回值。


二、“函数返回两次”的本质

回答问题二:

ps:fork本质上也是一个函数,这里有点像我们的函数里面有个函数进行调用的形式。

fork()  调用后,系统同时存在父进程和子进程两个独立进程:

- 在父进程中, fork()  返回子进程的 PID(大于 0 的整数)。
- 在子进程中, fork()  返回 0。
从“进程执行流”视角看, fork()  仿佛在父、子进程中各返回一次,因此呈现“返回两次”的效果。

三、进程资源与共享逻辑

- 代码共享:父、子进程的代码是共享的(代码通常为只读,可安全共享)。
- 数据独立:数据是各自独立的(若共享数据,修改后会导致父、子进程数据不一致,所以  fork()  会为子进程复制独立的数据副本)。(写识拷贝)

那么,如果父子进程被创建好,fork()往后,谁先运行呢?谁先运行,由调度器决定,不确定的。

因此,我们就可以回答第三个问题:3.一个变量怎么会有不同内容,如何理解?(如上)

四、创建子进程的目的与代码分支实现

- 目的:让父、子进程能执行不同的任务,实现多进程协作。
- 代码分支实现:利用  fork()  在父、子进程中返回值不同的特点(父进程返回子进程 PID,子进程返回 0),通过  if-else  判断返回值,让父进程和子进程进入不同的代码块执行(如父进程执行  id > 0  分支,子进程执行  id == 0  分支)。

bash通过创建子进程完成的,怎么创建?fork(),执行解释新命令

什么是bash??

bash”是Bourne-Again Shell的缩写,它是Linux和类Unix系统中最常用的命令行解释器(终端shell)。
简单来说,它的作用是:
- 接收并解释执行用户输入的命令,比如你在终端里输入的 ps 、 grep 这些指令,都是由bash来处理执行的。

区分bash与shell的区别:

Shell 是“命令解释器”的统称,bash 是 Shell 的一种具体实现,也是 Linux 中最常用的 Shell

进程状态

现在,我们来讲一下关于操作系统中常见的进程状态。

新建状态、就绪状态、运行状态、阻塞(阻塞/挂起)状态、终止状态

一、进程状态与生命周期

- 新建状态:进程刚被创建,尚未进入就绪队列。

- 就绪状态:进程已准备好执行,等待CPU调度。

- 运行状态:进程正在CPU上执行指令。

- 阻塞状态:进程因等待I/O事件等原因无法执行,需等待事件完成后回到就绪状态。

- 终止状态:进程执行完毕或异常退出。

- 状态切换:存在“新建→就绪→运行→阻塞→就绪”“运行→终止”等切换路径,体现进程在不同阶段的流转逻辑。

 二、进程调度与时间片

问题:一个进程只要把它自己放到CPU上开始运行了,是不是一直要执行完毕,才把自己放下来?

答案是:不是的,它其中会借助一个叫时间片的机制:

- 时间片机制:每个进程都有“时间片”(如10ms),进程在CPU上执行的时间不会无限长,时间片耗尽后会被调度器换下CPU,回到就绪队列,从而让其他进程获得执行机会

- 调度器与运行队列:通过 struct runqueue (运行队列)管理就绪进程, struct task_struct (进程控制块)记录进程的代码、数据及状态等信息,调度器负责从运行队列中选择进程分配CPU。

被放到运行队列的pcb,/就意味着告诉操作系统,我已经准备好了,可以随时进行调度!

三、并发执行与进程切换

- 并发的实现:在一个时间区间内,所有进程的代码通过“时间片轮转”被轮流执行,从而实现并发效果(宏观上多个进程同时运行)。

- 进程切换:大量进程在CPU上“被放上、被拿下”的动作即为进程切换,这是实现多任务并发的关键操作。

- 阻塞状态:进程因等待外设I/O(如键盘输入、磁盘读写)而无法执行的状态,需等待事件完成后才能回到就绪状态。
- 交换分区(swap):是磁盘上的一块区域,用于内存资源紧张时临时存储进程数据,实现内存与外存的“换入/换出”,保障多进程调度的连续性。
- 内存资源不足的调度
当“操作系统内部内存资源严重不足”时,会通过换出机制(将部分进程数据暂存到交换分区 swap )来“省出内存资源”,保证系统正常运行;当进程需要恢复执行时,再通过换入机制从 swap 分区将数据调回内存。
- 外设I/O的进程交互(以键盘为例)
进程发起键盘I/O请求后,若键盘处于“忙”状态,进程会被加入键盘的等待队列,进入阻塞状态;当键盘完成数据读取后,进程会被唤醒,从阻塞状态切换为就绪状态,等待CPU调度。(进程挂起状态)

总结:操作系统如何通过 struct dev 、 struct task_struct 等结构,结合内存换入换出、进程阻塞唤醒机制,实现外设I/O与内存资源的高效管理。

了解完进程状态后,,我们现在来认识一下:

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

R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里

S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))

D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。

X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态

Z僵死状态(Zombies)是一个比较特殊的状态。

产生原因:进程退出时,若父进程未主动回收子进程的退出信息,子进程会进入僵尸态,持续占用 task_struct  等资源。

资源影响:僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。若大量存在,会浪费系统资源。而且还会造成内存泄漏

回收方式:使用wait()系统调用

现实当中的僵尸进程是怎么样的?我们来实践一下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main()
{pid_t id = fork();if (id < 0){perror("fork");return 1;}else if (id > 0){ printf("parent[%d] is sleeping...\n", getpid());sleep(30);}else{printf("child[%d] is begin Z...\n", getpid());sleep(5);exit(EXIT_SUCCESS);}return 0;
}

父子进程特殊情况:

- 父进程先退出:子进程的父进程会被系统设置为 1 号进程( init  进程)。

- 孤儿进程:若父进程是 1 号进程,子进程成为孤儿进程,会由系统负责回收其资源(因为孤儿进程最终也会退出,系统需保障资源释放)。

我们改一下上面的代码,就能证明出来:

Linux 内核管理进程:

通过不同的链表(如运行队列链表、睡眠链表等)和树结构,内核可以高效地进行进程调度、资源管理和状态维护;偏移计算则保障了在链表操作中能准确关联进程控制块的完整数据。(如下图)

1.  struct node  双向链表结构
- 包含  struct node *next (指向下一节点)和  struct node *prev (指向上一节点),用于构建双向链表。
2.  struct task_struct  进程控制块
- 包含进程的所有属性,同时嵌入了  struct node1 link1  和  struct node link  两种链表节点结构,用于将进程加入不同的链表进行管理。
3. 树结构节点  struct node 
此外,它可以构建树结构(如红黑树)来组织进程。

二、链表与结构体的偏移计算
- 公式  (task_struct*)((start - &(task_struct*)0->link) -> A 用于计算  link  成员在  task_struct  结构体中的偏移量,通过指针运算实现从链表节点反向获取  task_struct  结构体的完整信息,是 Linux 内核中“容器_of”思想的体现(即通过结构体中某成员的指针,反推整个结构体的起始地址)。

进程优先级管理:

一、优先级的本质与意义

- 是什么:优先级是进程对资源(如CPU)访问的先后顺序规则,与“权限”不同(权限是能否访问资源,优先级是访问的先后)。
- 为什么需要:系统资源有限但进程众多,进程间存在资源竞争关系;操作系统需通过优先级保障进程良性竞争,避免进程长时间得不到资源而出现“饥饿问题”(代码长时间无法推进)。

二、优先级的表示与调整

(这个目前为止,几乎没怎么用过,看看以后有没有机会使用到)
- 关键字段(通过 ps -al 查看):

优先级公式:PRI(new)=PRI(old)+nice

ps:nice不是进程优先级,但它会影响进程优先级。
-  PRI :进程的优先级(数值越小,优先级越高)。
-  NI (nice值):优先级的修正数据,用于调整进程优先级。
- nice值范围: [-20, 19] ,Linux限制用户对优先级的过度调整,确保系统稳定性。
- 优先级计算:例如默认 PRI 为80时,调整 nice 值后, PRI 范围在 [60, 99] 之间( 80 + (NI的调整值) ,NI最小-20、最大19)。

UID : 代表执行者的身份

PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI :代表这个进程可被执行的优先级,其值越小越早被执行

NI :代表这个进程的nice值

renice的使用:

三、优先级调整的限制与意图

Linux不允许用户无限制调整优先级,仅在 [-20, 19] 范围内调整,防止进程因优先级过高长期占用CPU,或过低导致饥饿,保障系统整体调度的公平性与效率。

用top命令更改已存在进程的nice

进入top后按“r”–>输入进程PID–>输入nice值

这里就不演示了。

接下来,我们来讲解一下:

操作系统是如何根据优先级进行调度的?

通过位图的形式,我们已经在C++那边讲解过位图的知识点了。(若需要复习,可以去看看)



一、位图( struct bitmap )与快速查找
- 作用:用于快速判断资源(如进程队列是否为空),支持O(1)时间复杂度的查询,是Linux内核高效管理的基础(如判断队列是否为空仅需遍历位图)。
二、进程队列与调度组( struct rungqueue )
- 调度效率:通过将进程按优先级分组到不同队列,结合位图的快速判断,实现高效的进程调度与饥饿问题缓解(确保不同优先级进程都能获得合理的CPU时间)。

好了,本次就分享到这里了,下一次继续。希望大家一起进步!

最后,到了本次鸡汤环节:

我希望,我的希望,有希望。

http://www.dtcms.com/a/399392.html

相关文章:

  • w32time 服务
  • 视频解析网站怎么做的wordpress阿里云卡死了
  • 审美积累,顶刊论文插图原理图、流程图
  • 网站开发上市公司做彩票网站犯法不
  • python+django/flask在线问诊系统 医院就诊 医生推荐系统
  • 【Qt】QButtonGroup、QToolButton、QStackedWidget的常用用法
  • QT:串口通信、串口发送与接收(2)
  • 【Unity 入门教程】一、前置工作
  • 北京网站建设公司空间续费北京建设工程施工司法解释
  • 需求收集不完整的常见原因有哪些
  • 论坛网站备案开发者选项在哪里打开vivo
  • 谈谈数组和链表的时间复杂度
  • ServletContex读取properties文件,中文乱码
  • todesk取消客户端开机自动启动后,开机仍然会启动客户端,怎么设置?
  • C++编程学习(第36天)
  • 如何快速处理电脑上常常遇到的各种小问题?
  • 卷积神经网络(CNN)的LeNet模型
  • 佛山网站外包什么是网站推广方案
  • 合肥门户网站制作建设佛山cms建站
  • Linux命令大全-usermod命令
  • Linux网络HTTP协议(上)
  • 开源 java android app 开发(十四)自定义绘图控件--波形图
  • umijs 4.0学习 - umijs 的项目搭建+自动化eslint保存+项目结构
  • 汇天网络科技有限公司苏州关键词优化软件
  • 制冷剂中表压对应温度值的获取(Selenium)
  • 建什么网站访问量高seo优化
  • 小型网站建设参考文献word超链接网站怎样做
  • 可视化 GraphRAG 构建的知识图谱 空谈版
  • 安装gitlab并上传本地项目
  • 黄页88网站免费推广网站大全网