news 2026/4/24 18:10:14

LINUX系统编程-进程概念

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LINUX系统编程-进程概念

在linux系统中,对于进程管理,文件系统和设备驱动,都是通过先描述再组织的方式进行管理。那么,什么是先描述,什么是后组织呢?

简单来说,先描述的意思就是,将数据,通过结构体进行封装,实现将数据给对象化。后组织,就是将这些对象,通过数据结构(链表,队列,堆栈)进行连接,使其建立联系,实现高效关联。

进程概念

接下来,我们来了解一下,什么叫做进程。在课本上,进程的描述颇为复杂,但是我们在这,就对进程下一个绝对正确的定义:

进程=内核数据机构对象+自己的代码与数据

在课本上,我们将这个对象称之为PCB(process control block),这个对象就是用来描述进程的属性的。在linux系统中,PCB就是task_struct,这是linux底层用c++封装的一种数据结构,它存放于RAM中。所有运行在系统的进程都以task_struct双链表的形式存放在内核中,因此,我们通过一个进程,理论上可以找到其他的进程。我们需要知道的是,我们历史上执行的所有指令,工具,gcc编译后的程序,都是进程。

所有的进程都存放在/proc/这个目录下,如果我们对这个目录进行ls,我们会看到一堆数字,此时我们再直接执行ps -ajx ,我们也会也会看到一堆数据,其中,PID的数据就是/proc目录下的对应的数字。此时我们再ls -l,我们会看到两个符号链接,一个是exe,一个是cwdexe,我们在Windows系统中也非常常见了,他就是可执行文件,通过ls -l,我们会看到他后面跟着一个地址,就是指向那个可执行文件。接着是cwd,他的意思是当前工作目录,指向的是进程当前所在的目录。我们通过chdir可以改变这个路径的指向。

在c语言中,我们可以通过fork来创建子进程,fork一种写时拷贝的显著例子。那么,写时拷贝是什么呢?简单来说,当我们在父进程创建一个子进程的时候,理论上我们需要把父进程的资源全部复制一遍给子进程,但是如果父进程很大(几个G)时,这样子会很浪费时间和空间,因此,在只读的情况下,此时子进程和父进程是共用父进程的资源的。当其中一个进程需要改数据,动资源的时候,会触发缺页中断,此时内核才会申请新的空间,把数据进行复制,保证父子进程都有自己的空间。我们举一个生活中的例子:

想象你和同学合写一份报告:

  • 没有 COW:我先复印 50 页纸给你。你拿过去可能一张没改,这 50 页纸就浪费了。

  • 使用 COW:我发给你一个只读链接

    • 如果你只是看,我们共用这一份云端文档。

    • 一旦你想在某一段加上你的名字,系统瞬间帮你生成一个这页文档的私人副本供你编辑。

这就是写时拷贝的精妙之处了。然后这里,我们还需要注意的是,如果在新创空间之前,我们把父进程给关了,此时原共享的资源就属于子进程了,并且该资源的权限由“只读”变成了“可写”。

接下来我们再来讨论fork的返回值问题,其实其本质也是写实拷贝。当我们运行如下代码时,我们会发现终端会同时处理父子进程的逻辑,为什么fork会返回两个值呢?其实,并不是fork返回了两个值,而是父子进程,各返回了一个值。fork以后,父进程会返回子进程的pid,因为一个父进程可能有多个子进程,它需要知道现在生成的这个子进程是谁。子进程会返回0,因为子进程只有一个父进程,他只需要通过get_ppid()函数就能知道他的父进程是谁,因此返回0就可以。刚 fork 完:父子进程的变量id理论上指向同一个物理地址。写入返回值:内核在返回时,实际上是在向id变量写入数据。因此,在最后返回PID的时候,实际上是两个进程再交互工作。

pid_t id = fork(); if (id < 0) { // 出错 } else if (id == 0) { // 子进程逻辑 } else { // 父进程逻辑 }

进程状态

在linux中,进程主要有以下几种状态:

1.R running(运行):代表进程处于运行状态在在运行队列里,这处决于系统本身。

2.S sleeping(睡眠):通常也会被称之为阻塞。其是一种等待状态,在等待某种事件完成,该状态可以被系统强行中断,其资源此时依然保存在ram中,比如,若此时系统负载过高,系统可能就会强行释放睡眠状态的资源。

3.D Disk sleep(磁盘睡眠):有时候也叫不可中断睡眠状态(uninterruptiblesleep),在这个 状态的进程通常会等待IO的结束,无法用kill -9杀死进程。

4.T stop(停止):相比于睡眠状态,stop状态更多是外部强制中断暂停,比如我在在运行程序时,可以使用ctrl +z 的方法强行中断暂停某个进程,也可以敲SIGSOT进行暂停。此时,再按下fg(前台运行)或者bg(后台运行)即可恢复进程。

5.t tracing stop(可追踪停止):该状态和T状态类型,但是这个状态通常出现在调试阶段,当我们使用gdb等调试软件调试的时候,再通过ps查状态,就能看到小t.

6.Zzombie(僵尸):僵尸状态是进程退出后、彻底消失前的一个过渡状态。只要子进程退出,父进程还在运行但未调用wait读取退出状态,子进程就会成为僵尸进程,导致 PID 等内核资源无法回收(造成内核内存泄漏)。

如果父进程在未收尸的情况下退出,这些僵尸子进程会被1号进程(init/sysemd)领养。1号进程会自动读取它们的退出状态并释放剩余资源,从而清理掉这些僵尸

7.X dead(死亡):就是进程完全结束,但是一般我们看不到这个状态,在僵尸状态以后立刻就是X状态。

ps aux / ps axj

我们日常可以使用上述命令查询进程状态。

其实在状态之外,还有一种现象叫做挂起,挂起和阻塞有些不同,挂起指的是当CPU的内存严重不足时,内核会将RAM中的存储给放到磁盘中一个叫swap空间中,此时,他的PCB还在内核的队列中,但是他的资源已经指向了磁盘的一处swap空间。当后续CPU想要运行该进程时,需要先将相关资源从磁盘中再swap回来到RAM中,然后才能开始运行该进程。

每个CPU核心都会存在一个runqueue,这个队列里面会存放那些处于running状态的进程,cpu核心会根据该队列的顺序,依次执行进程。当某个进程进入了S/D状态,那么就会从runqueue脱离出来,转而进入waitqueue队列。因此,进程的变化,表现之一,就是在不同队列中进行流动,实现对相关数据结构的增删查改。

那么,我们现在再回去看一下,linux的PCB中,双链表到底是怎么实现的呢?其实,在task_struct中,双链表并不是直接以prenode和nextnode节点直接连接的,task_truct内部封存了一个struct某一个list_head的结构体,这个对象里面只存prenode和nextnode,为什么要这么做呢?这是为了让某一个task_struct,能隶属于不同的数据结构。比如,我现在一个task_strcut,他可能要在系统的双链表中,也有可能要在运行队列中,如果只有直接使用prenode和nextnode,将会非常痛苦,此时,我们只要往里面再加一个list_head就可以了。有人会问了,这样设计,不会导致手里只有一个list_head的指针,怎么知道它属于哪个 task_truct 呢?这一点,我们就需要回到c语言中结构体的基本知识了。当我提到“内存对齐”,“漂移量”的时候,你应该就懂了。

struct task_struct { struct list_head tasks; // 全局链表的“钩子” struct list_head run_list; // 运行队列的“钩子” struct list_head children; // 子进程链表的“钩子” };
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/24 18:06:41

告别手机小屏幕!酷安UWP让你在Windows电脑上高效刷酷安的神奇体验

告别手机小屏幕&#xff01;酷安UWP让你在Windows电脑上高效刷酷安的神奇体验 【免费下载链接】Coolapk-UWP 一个基于 UWP 平台的第三方酷安客户端 项目地址: https://gitcode.com/gh_mirrors/co/Coolapk-UWP 还在为手机刷酷安而眼睛酸痛吗&#xff1f;想在大屏幕上舒适…

作者头像 李华
网站建设 2026/4/24 18:03:42

DeepSeek正式发布:你需要知道的6个重点

DeepSeek正式发布&#xff1a;你需要知道的6个重点 2026年4月&#xff0c;DeepSeek V4 终于正式发布了。 从2025年初V3和R1的惊艳亮相&#xff0c;到V4的漫长等待期&#xff0c;这个来自中国的AI实验室始终保持着"低成本、高性能"的路线。 如果你关注AI圈&#xff0c…

作者头像 李华
网站建设 2026/4/24 17:54:54

AI辅助UI设计全流程:从需求描述到高质量出图的完整步骤大全

一款产品从构想落地到可交付的视觉稿&#xff0c;传统流程通常需要产品经理、UI设计师、前端开发者之间反复拉齐&#xff0c;周期动辄两周起步。随着 AI 辅助设计工具进入实际工作流&#xff0c;这条链路的时间结构正在发生根本性的变化。本文以 UXbot 为例&#xff0c;完整拆解…

作者头像 李华
网站建设 2026/4/24 17:53:21

3步实现群晖NAS与百度网盘自动同步:告别繁琐手动操作

3步实现群晖NAS与百度网盘自动同步&#xff1a;告别繁琐手动操作 【免费下载链接】synology-baiduNetdisk-package 项目地址: https://gitcode.com/gh_mirrors/sy/synology-baiduNetdisk-package 还在为群晖NAS和百度网盘之间的文件传输而烦恼吗&#xff1f;每次手动上…

作者头像 李华
网站建设 2026/4/24 17:51:23

ModTheSpire终极指南:5分钟学会安全安装和管理杀戮尖塔游戏模组

ModTheSpire终极指南&#xff1a;5分钟学会安全安装和管理杀戮尖塔游戏模组 【免费下载链接】ModTheSpire External mod loader for Slay The Spire 项目地址: https://gitcode.com/gh_mirrors/mo/ModTheSpire 你是否厌倦了杀戮尖塔的原有玩法&#xff1f;想要体验全新角…

作者头像 李华
网站建设 2026/4/24 17:47:39

MySQL Innodb 页缓存管理原理

MySQL InnoDB页缓存管理原理探秘 在数据库性能优化中&#xff0c;InnoDB存储引擎的页缓存&#xff08;Buffer Pool&#xff09;机制是核心组件之一。它通过内存缓存数据页&#xff0c;减少磁盘I/O操作&#xff0c;显著提升查询效率。理解其管理原理&#xff0c;对数据库调优和…

作者头像 李华