Linux进程(上)

什么是进程

进程(Process) ,官方解释为 计算机中已运行程序的实体是系统进行资源分配与调度的基本单位。

在计算机中,程序是指令、数据及其组织形式的描述,而进程则是程序的实体,一个进程是由 PCB + 数据 构成的。。

(PCB 是一个结构体,里面是该进程的属性,可以理解为进程的 "身份证" )

进程是具体的,它具有动态性,也被认为是一个 "过程" ,因为它随着指令的执行不断改变,它会被创建,运行,销毁。

Linux 下的进程

进程在不同操作系统下的实现不同,但进程的底层逻辑在任何操作系统下都是一样的,本文只是在 Linux 下进行讲解,所述的进程知识并非 Linux 特有

PID:

使用指令可以查看当前所有进程:

可以看到进程有很多的信息,我标记出了一个名为 :PID的标记,这是进程号,就是进程的 "身份证号" 。

进程像树一样分父和子(结构不是树),一个进程可以用 fork 进行 "复制" ,原来的进程变成了父进程 ,复制出来的进程就是它的子进程,一个父进程可以有多个子进程 。可以编写程序通过 getpid 和 getppid 来分别查看当前进程的 PID 和 其父进程的 PID :

也可以用 ps -ef | grep (执行的文件名)来查看 PID ,但是这种方法要开两个终端窗口。

奇怪的 fork :

前面提到了 fork ,这家伙其实有点古怪的地方,我们通过一个程序来看看:

从该程序可以得到一个惊人的信息:fork 竟然能有不同的返回值,id 竟然能接收不同的返回值。这个结论好像颠覆了以前学习的 C语言 逻辑,应该怎么解释这种情况呢?

前面有说到,fork 的作用是把当前进程复制一份。但这个复制的行为其实在 fork 里面就已经完成了,并且子进程 已经开始运行,于是就有了两个独立的进程,它们执行各自的 return ,父进程 返回的是子进程 的 PID ,而子进程返回 0。

那 id 变量如果做到接收两个不同的值的呢?答案是: "一个变量同时有两个值" 只是表面,底层其实有两个 id ,它们只是名字一样。这涉及到 虚拟内存空间 的知识,这里不细讲,但可以理解为:fork 在复制子进程 出来时,把 id 也复制了一份 ,这样父进程子进程就有不同的变量了。

写时拷贝:

fork 在进行 复制 时,按理说应该完全复制一份父进程 的副本来作为子进程 ,但一个进程包含的数据量可能会很大,如果对这对父子进程 只进行读操作,那么这个复制就很没有性价比了!为了 "偷懒" ,Linux 在复制时并不会直接把所有数据都复制一份,而是只复制 页表 (页表,是操作系统给每个进程配的「地址翻译 + 内存账本」,把虚假的虚拟地址,翻译成真实的物理内存地址),让父子进程 指向同一块物理地址,只有当父进程子进程 任意一方要对数据进行 "写" 操作时,才真正进行数据拷贝,这就是 写时拷贝 。它大大节省了内存,也提高了程序运行效率。

进程状态

进程的标准状态:

进程有三种标准状态:就绪,运行,阻塞 ,后面扩展出了 挂起 状态。在 Linux 中,用不同字母来表示不同的状态:

(R 合并了 就绪 和 运行 ,S/D 就是 阻塞 状态,T 是 挂起)

就绪运行 从字面上理解就可以了,重点讲一下 阻塞 和 挂起 。

阻塞 ,可以理解为进程正在等待,它不占用 CPU 资源 ,但赖在 内存 中不走。像 C语言 中,使用 scanf 获取输入就会让进程进入阻塞状态,此时进程就是在等待输入。S 状态 和 D 状态 都是阻塞,但 S 是可中断的,也可以使用 kill 指令杀死,而 D 状态则不行,它必须等到所需要的资源,不可中断,不可杀死。

挂起 ,相当于暂停,分两种。第一种是用 T 状态表示的挂起,这种挂起是手动 的,是被外力强制按下的暂停,比如 Ctrl + Z ,还有调试时的断点(用 t 表示),手动的挂起不会自己启动,必须手动恢复。第二种是内存管理挂起 ,在 内存紧张 时,OS(操作系统)将暂时用不上的进程挂到磁盘中,属于内存调度的手段之一。

Linux 的特殊进程状态:

I,Z,X 都是 Linux 特有进程状态,其中值得一讲的是 Z僵尸进程

前面提到过父子进程的概念,当子进程先于父进程退出(此时是 X,死亡状态),但父进程没有调用 wait / waitpid 回收其退出状态,这个子进程就变成了一个僵尸进程

僵尸进程无法被 kill 杀死,它的 PCB 无法被释放,留着内存中,会导致内存泄漏 ;僵尸进程不占用 CPU 资源,但是会占用 PID 资源 ,若存在大量僵尸进程,会导致新的进程无法被创建,系统崩溃

解决方法是:重启父进程 ,这样父进程死了,僵尸进程会被 init 回收,或者调用 wait / waitpid回收子进程的退出信息。

我们可以模拟出一个僵尸进程并查看其状态:

运行并查看:

STAT 这一列表示的就是进程状态,后面会讲到。

查看进程状态:

可以用 ps aux 所有进程的状态,如果要查看特定进程可以用管道符结合 grep 进行指定。

前面提到,STAT 这一列的符号表示的就是进程的状态,可是我们发现,在有些进程的字母后面还跟着一些符号,这些其实是 状态修饰符,下面列举一些常见的状态修饰符(不做细致讲解):

相关推荐
feng_you_ying_li2 小时前
linux之git/gdb的使用与介绍
linux
FreeBuf_2 小时前
Nginx-UI 备份恢复漏洞 PoC 公开:攻击者可篡改加密备份并注入恶意配置
运维·nginx·ui
吕司2 小时前
Linux页表的概念
linux·运维·服务器
ShineWinsu2 小时前
对于Linux:环境变量的解析
linux·面试·笔试·进程·环境变量·本地变量·getenv
坚持就完事了2 小时前
Linux上编写和运行Python\Java
linux·运维·服务器
wal13145202 小时前
OpenClaw 2026.4.5:视频/音乐生成内置,11 种语言支持,多个安全修复
运维·服务器·人工智能·安全·openclaw
超绝振刀怪2 小时前
【Linux 环境变量和地址空间】
linux·环境变量·fork·写诗拷贝
OPHKVPS2 小时前
Anthropic官方Git MCP服务器曝三重漏洞:提示注入即可实现文件读写与远程代码执行
运维·服务器·git
正经教主2 小时前
【docker基础】第三课:镜像管理与Dockerfile基础
运维·docker·容器