进程是 Unix 和 Linux 系统中对正在运行中的应用程序的抽象,通过它可以管理和监视程序对内存、处理器时间和 I / O资源的使用。程序被触发后,执行者的权限与属性、程序的程序代码与所需数据等都会被加载内存中,操 作系统并给予这个内存内的单元一个标识符 (PID),可以说,进程就是一个正在运作中的程序。

进程空间管理图片

一)Linux 进程的主要构成部分
在 Linux 中,进程是程序执行的实例。每个进程都有一系列的属性和资源来支持其运行。以下是 Linux 进程的主要构成部分:
1)进程 ID(PID)
进程 ID(Process ID,PID)是 Linux 操作系统为每个进程分配的唯一标识号。PID 由内核在进程创建时分配,用于管理和跟踪进程。
- 每个进程都有一个唯一的标识符,称为进程 ID(PID)。
- 它用于标识进程,以便操作系统能够管理和控制进程。
- 默认情况下,PID 的范围为 0 到 32768,可以通过
/proc/sys/kernel/pid_max
查看或修改。 - PID 0 通常代表
swapper
(调度器进程),它负责 CPU 空闲时的任务调度。 - PID 1 是
init
或systemd
进程,负责启动和管理所有其他进程。 - PID 2 代表
kthreadd
,是 Linux 内核的线程管理进程。 - 当一个进程结束后,其 PID 可能会被新的进程重新使用。
2)父进程 ID(PPID)
父进程 ID(Parent Process ID,PPID) 是指创建当前进程的父进程的进程 ID(PID)。在 Linux 中,所有进程(除了 init
或 systemd
进程)都有一个父进程。PPID 用于建立进程之间的层级关系。每个进程都有一个父进程 ID(PPID),表示它是由哪个进程创建的。
3)进程状态
在 Linux 操作系统中,每个进程都有一个状态,表示其当前的执行情况。进程的状态反映了它当前的活动或生命周期阶段,进程状态决定了 CPU 何时调度该进程执行,或者它是否在等待某些事件发生。
状态 | 缩写 | 说明 |
---|---|---|
运行(Running) | R |
进程正在运行或准备运行(等待 CPU 调度)。 |
可中断睡眠(Sleeping) | S |
进程在等待某个事件(如 I/O)完成,可以被信号唤醒。 |
不可中断睡眠(Uninterruptible Sleep) | D |
进程等待不可中断的事件(如磁盘 I/O),不会被信号唤醒。 |
停止(Stopped) | T |
进程被暂停,通常由 SIGSTOP 、SIGTSTP 信号触发。 |
僵尸(Zombie) | Z |
进程已终止,但父进程未回收,仍占用进程表。 |
如何处理不同进程状态
状态 | 处理方式 |
---|---|
运行(R) | 正常进程,无需处理 |
可中断睡眠(S) | 可使用 kill 终止 |
不可中断睡眠(D) | 可能是 I/O 问题,需检查硬件或驱动 |
停止(T) | 可用 kill -CONT <PID> 恢复执行 |
僵尸(Z) | 终止父进程(kill <PPID> ) 或让父进程调用 wait() |
- Linux 进程有多种状态,最常见的是 运行(R) 和 睡眠(S)。
- 不可中断睡眠(D) 进程可能因 I/O 操作卡住,需检查系统状态。
- 僵尸进程(Z) 需要父进程回收,或者终止父进程释放资源。
- 使用
ps
、top
或/proc
文件系统可以查看进程状态,使用kill
终止进程或fg/bg
控制进程运行。
4)内存映像
在 Linux 操作系统中,每个进程在运行时都会占用一定的内存空间,这部分内存称为进程的内存映像(Memory Image)。进程的内存映像由多个不同的区域组成,包括代码段(Text Segment)、数据段(Data Segment)、堆(Heap)、栈(Stack) 等。
4.1) 进程内存布局(Memory Layout)
Linux 进程的虚拟地址空间通常分为以下几个主要部分(从低地址到高地址):
区域 | 作用 | 特点 |
---|---|---|
代码段(Text Segment) | 存放程序的可执行代码 | 只读、共享 |
数据段(Data Segment) | 存放已初始化的全局变量和静态变量 | 读写 |
BSS 段(BSS Segment) | 存放未初始化的全局变量和静态变量 | 初始值为 0 |
堆(Heap) | 用于动态内存分配(malloc /new ) |
向高地址扩展 |
共享库(Shared Libraries) | 存放动态链接库(*.so 文件) |
共享、多进程复用 |
栈(Stack) | 存放函数调用、局部变量、返回地址 | 向低地址扩展 |
4.2) 进程内存布局示意图

4.3) 进程的内存区域详解
每个进程都拥有自己独立的内存空间,其中包括以下几个区域:
- 代码段(Text Segment)
- 数据段(Data Segment)
- 堆(Heap)
- 栈(Stack):用于存储函数的局部变量和函数调用的返回地址。
- BSS段:存储未初始化的全局变量。
4.3.1)代码段(Text Segment)- 存储程序的可执行代码。存放程序代码。正文段具有只读的属性。
例如
int main() { printf("Hello, world!\n"); return 0; }
4.3.2)数据段(Data Segment)
用户数据段(user segment):是进程在运行过程中处理数据的集合,它们是 进程直接进行操作的所有数据(包括全部变量在内),以及进程使用的进程堆栈, 系统数据段(system segment):存放着进程的控制信息,即进程控制块(PCB ,Processing Control Block),名字为task_struct的数据结构。 存储静态变量和初始化的全局变量。
1、用户栈区(供用户程序使用的信息区);
2、用户数据区(包括用户工作数据和非可重入的程序段);
3、系统数据区(包括系统变量和对换信息)
- 正文段
程序段是可重入的程序,能被若干进程共享。为了管理可共享的正文段,Linux设置了一张正文表,每个正文段都占用一个表目,用来指出该正文段在内存和磁盘上的位置、段的大小以及调用该段的进程数等情况。
例如
int global_var = 10; // 存放在数据段 static int static_var = 20; // 也存放在数据段
4.3.3) BSS 段(未初始化数据段)
- BSS(Block Started by Symbol)存放未初始化的全局变量和静态变量。
- BSS 段的内容默认初始化为 0,但不会占用可执行文件的实际空间(仅在运行时分配)。
例如
int global_var_uninit; // 存放在 BSS 段,值默认为 0 static int static_var_uninit; // 也存放在 BSS 段
4.3.4) 堆(Heap)
- 堆用于动态内存分配(如
malloc()
、calloc()
、new
)。 - 向高地址扩展,如果堆空间不足,会触发
brk()
或mmap()
系统调用扩展堆空间。 - 堆分配的内存需要手动释放,否则可能会导致内存泄漏。
示例
#include <stdlib.h> int main() { int *p = (int *)malloc(sizeof(int) * 10); // 在堆上分配 10 个 int free(p); // 释放内存,避免内存泄漏 return 0; }
malloc()
申请的内存来自堆,free()
释放后归还给系统。
4.3.5) 共享库(Shared Libraries)
ldd /bin/ls
输出
linux-vdso.so.1 => (0x00007fff5d1d3000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0cbb24a000) /lib64/ld-linux-x86-64.so.2 (0x00007f0cbb60a000)
4.3.6) 栈(Stack)
用于存储函数的局部变量和函数调用的返回地址。
- 栈用于函数调用、局部变量存储,包括:
- 函数的返回地址
- 局部变量
- 参数
- 向低地址扩展,如果栈溢出,会触发
segmentation fault
。 - 每个线程都有自己的栈。
例如,
void func() { int x = 10; // 局部变量 x 存放在栈上 }
x
变量分配在栈上,函数返回后被自动释放。
4.4)进程的内存映射
Linux 允许进程使用 mmap()
系统调用直接映射文件或设备到进程地址空间。可以通过 /proc/<PID>/maps
查看进程的内存映射情况。
例如
cat /proc/$(pgrep bash)/maps
结果
00400000-00452000 r-xp 00000000 08:01 1234567 /bin/bash 00651000-00652000 r--p 00051000 08:01 1234567 /bin/bash 00652000-00653000 rw-p 00052000 08:01 1234567 /bin/bash
r-xp
:可读、可执行、私有(代码段)。rw-p
:可读、可写、私有(数据段、堆、栈)。
4.5)进程内存查看工具
五)文件描述符(File Descriptors)
在 Linux 和 Unix 系统中,文件描述符(File Descriptor,FD) 是进程用于访问文件、管道、套接字、设备等的一种抽象标识符。
本质上,它是一个非负整数,用于标识进程打开的文件或 I/O 资源。
文件描述符 | 名称 | 作用 | 默认设备 |
---|---|---|---|
0 |
标准输入(stdin) | 读取输入数据 | 键盘 |
1 |
标准输出(stdout) | 输出正常信息 | 终端 |
2 |
标准错误(stderr) | 输出错误信息 | 终端 |
一个文件描述符的生命周期包括:
- 分配:进程使用
open()
、socket()
、pipe()
等系统调用打开文件或资源,系统返回一个文件描述符。 - 使用:进程通过
read()
、write()
、send()
、recv()
等操作读写文件描述符指向的资源。 - 关闭:进程调用
close(fd)
释放文件描述符,防止资源泄漏。
六)进程权限
七)进程之间的通信信号(Signals)
在 Linux 和 Unix 系统中,信号(Signal) 是一种进程间通信(IPC)机制,用于通知进程发生了某种事件。信号是一种异步的通知方式,操作系统或其他进程可以随时向目标进程发送信号,以让其执行特定的操作,如终止、暂停、继续运行等。
- 信号是进程间的异步通知机制,可以用于通知进程某个事件发生,如中断、终止、挂起等。
- 进程可以接收、忽略、处理信号(但某些信号无法被捕获或忽略,如
SIGKILL
)。 - 信号是由 内核、用户、硬件 触发的。
- 进程可以使用
kill
命令或kill()
系统调用向其他进程发送信号。

八)调度信息
九)上下文信息
十)PCB进程控制块
在Linux成功fork进程后,会在系统中创建一个task_struct(也称PCB, process control block),用来描述当前进程的状态、进程间关系、优先级和资源等信息。
PCB(进程控制块) 结构体 task struct,负责管理进程的所有资源,它的成员 mm_struct 指向这个进程相关的内存资源,mm_struct指向一个结构体,包括:
- 栈 :给局部变量(自动变量)分配空间的地方
- 堆 :使用malloc、new… 分配的空间(也叫自由区)
- BSS段
- 数据段
- 代码段:代码区是只读的,程序代码会被读入此区,程序执行期间执行的就是代码区中的代码。
- 进程控制块(PCB)是操作系统用来保存进程信息的数据结构。
- PCB 包含进程的所有信息,如 PID、父进程 PID、进程状态、寄存器值、内存管理信息等。

- 标识符: 与进程相关的唯一标识符,用来区别正在执行的进程和其他进程。
- 状态: 描述进程的状态,因为进程有挂起,阻塞,运行等好几个状态,所以都有个标识符来记录进程的执行状态。
- 优先级: 如果有好几个进程正在执行,就涉及到进程被执行的先后顺序的问题,这和进程优先级这个标识符有关。
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 程序代码和进程相关数据的指针。
- 上下文数据: 进程执行时处理器的寄存器中的数据。
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表等。
- 记账信息: 包括处理器的时间总和,记账号等等。
PCB中包含4个部分
1.进程标识信息:用于唯一地标识一个进程,一个进程通常有两种标识符:
- 内部标志符: 由操作系统赋予每个进程的一个唯一的数字标识符,它通常为一个进程的序号,方便了系统使用。
- 外部标识符: 由创建者产生,是由字母和数字组成的字符串,为用户进程访问该进程提供方便。
- 为了描述进程间的家族关系,通常还设有父进程标识和子进程标识,以表示进程间的家族关系。
- 此外,还设有用户名或用户标识号表示该进程属于哪个用户。
2.处理机状态
- 处理机状态信息主要由处理机的各个寄存器内的信息组成。 进程运行时的许多信息均存放在处理机的各种寄存器中。其中 程序状态字(PSW) 是相当重要的,处理机根据程序状态寄存器中的PSW来控制程序的运行。
3.进程调度信息
- 进程状态: 标识进程的当前状态(就绪、运行、阻塞),作为进程调度的依据。
- 进程优先级: 表示进程获得处理机的优先程度。
- 为进程调度算法提供依据的其他信息:例如,进程等待时间、进程已经获得处理器的总时间和进程占用内存的时间等。
- 事件: 是指进程由某一状态转变为另一状态所等待发生的事件。(比如等待I/O释放)
4.进程控制信息
- 程序和数据地址: 是指组成进程的程序和数据所在内存或外存中的首地址,以便在调度该进程时能从其PCB中找到相应的程序和数据。
- 进程同步和通信机制: 指实现进程同步和通信时所采取的机制,如消息队列指针和信号量等,他们可以全部或部分存在PCB中。
- 资源清单: 列出了进程所需的全部资源 及 已经分配给该进程的资源,但不包括CPU.
- 链接指针: 它给出了处于同一队列中的下一个PCB的首地址。
一个 Linux 进程由多个部分组成,包括进程 ID、内存映像、文件描述符、权限、调度信息等。操作系统利用这些信息管理和控制进程的创建、执行、暂停、终止等各个生命周期步骤。