【Linux 系统编程核心】进程的本质、管理与核心操作

一、进程的核心定义与本质

1.1 进程是什么?

进程是程序的一次执行过程,是操作系统分配内存、CPU 等资源的基本单位。简单来说:

  • 程序:存储在硬盘上的代码、数据的静态集合(如a.outls命令);
  • 进程:程序加载到内存中运行的动态过程,包含创建、调度、消亡全生命周期。

1.2 进程与程序的核心区别

维度 程序 进程
状态 静态(永存) 动态(暂时,有生命周期)
特性 无状态变化、无并发 有状态切换、支持并发
资源 不占用系统资源 占用 CPU、内存、文件描述符等资源
运行关系 一个程序可运行多次,生成多个进程 一个进程可加载运行一个 / 多个程序
竞争关系 无资源竞争 多进程会竞争 CPU、内存等系统资源

示例:1.c编译为a.out(程序,静态),执行./a.out后生成一个 PID 为 xxx 的进程(动态),多次执行./a.out会生成多个独立进程。

1.3 PCB:进程的 "身份证"

Linux 系统通过PCB(Process Control Block,进程控制块) 管理进程,PCB 是内核中的结构体,存储进程的所有核心信息,核心字段包括:

  • PID:进程唯一标识符(进程 ID);
  • 当前工作路径(可通过chdir修改);
  • umask:文件创建默认权限掩码(如0002);
  • 进程打开的文件列表(文件描述符表);
  • 信号相关设置(处理异步 IO);
  • 用户 ID / 组 ID:进程的权限归属;
  • 内存映射:进程的虚拟内存空间映射;
  • 进程状态:运行、休眠、停止等。

1.4 进程的资源限制

Linux 对进程的资源使用有严格限制(可通过ulimit查看 / 修改),常见限制:

  • 最大打开文件数:默认 1024;
  • 栈大小:默认 8M;
  • 最大虚拟内存:受系统物理内存限制;
  • CPU 时间片:由调度算法分配。

二、进程的核心特性

2.1 虚拟内存:进程的 "内存隔离墙"

Linux 为每个进程分配独立的虚拟内存空间(默认 0-3G 用户空间 + 3-4G 内核空间),核心作用:

  1. 隔离性:A 进程无法直接访问 B 进程的内存空间,避免数据篡改;
  2. 安全性:通过权限控制进程访问内核空间,防止任意操作系统内核;
  3. 灵活性:进程无需关心物理内存地址,由内核完成虚拟地址到物理地址的映射。

2.2 进程的分类

根据运行特性,Linux 进程可分为三类:

  1. 交互式进程 :依赖用户输入触发运行,如vimbashssh,需等待用户操作(输入命令、点击按钮);
  2. 批处理进程 :无需用户交互,批量执行命令,如 shell 脚本、定时任务(crontab);
  3. 守护进程 :后台自动运行,默认休眠,满足特定条件时触发(如系统更新进程、杀毒软件、nginx服务),通常以d结尾(如sshdcrond)。

2.3 进程的核心作用:并发

并发是操作系统的核心能力 ------宏观并行,微观串行

  • 宏观:一个时间段内,多个进程看似 "同时运行"(如边刷浏览器边听音乐);
  • 微观:某一时刻,CPU 仅能运行一个进程(单核),通过进程调度实现 "并发"。

三、进程的状态与调度

3.1 Linux 进程状态(核心)

进程在生命周期中会在多个状态间切换,通过ps aux可查看状态(STAT列):

状态标识 含义 说明
R(Running) 运行 / 就绪 正在 CPU 运行,或等待 CPU 时间片
S(Sleeping) 可中断休眠 等待事件触发(如 IO、信号),可被信号唤醒
D(Uninterruptible Sleep) 不可中断休眠 等待 IO(如磁盘读写),不可被信号唤醒
T(Stopped) 停止 SIGSTOP信号暂停,可被SIGCONT唤醒
Z(Zombie) 僵尸进程 进程已终止,但父进程未回收其资源(PID 仍存在)

3.2 进程调度算法

Linux 内核需合理分配 CPU 时间片给多个进程,常见调度算法:

  1. 时间片轮转:每个进程分配固定时间片(如 10ms),用完后切换到下一个进程;
  2. 短任务优先:优先调度运行时间短的进程,减少总等待时间;
  3. 进程优先级:优先级高的进程优先获取 CPU(Linux 优先级范围 0-139,数值越小优先级越高);
  4. 完全公平调度(CFS):Linux 默认调度算法,按进程的 "CPU 使用占比" 公平分配时间片。

3.3 进程上下文切换

当进程的 CPU 时间片耗尽,内核会切换到下一个进程,这个过程称为 "上下文切换":

  1. 暂停当前进程(如a.out),将其状态(PCB、寄存器、PC 指针、内存数据)保存到硬盘 / 内存;
  2. 释放 CPU 资源,加载下一个进程(如b.out)的上下文数据到内存;
  3. 恢复下一个进程的运行状态,使其占用 CPU 继续执行。

上下文切换会产生一定开销,过度切换会降低系统性能。

四、进程管理的核心命令

4.1 查看进程

命令 功能 示例
ps aux 显示所有进程的详细信息(PID、状态、CPU 占用等) `ps aux grep a.out(过滤a.out` 进程)
top 实时监控进程(Linux 版 "任务管理器") P按 CPU 排序,按M按内存排序
pstree 以树形结构显示进程间的父子关系 pstree -p(显示 PID)

4.2 终止进程

命令 功能 示例
kill [信号] PID 向指定 PID 进程发送信号 kill -9 12345(强制终止 PID=12345 的进程)
killall [信号] 进程名 终止所有同名进程 killall -9 a.out(终止所有a.out进程)
pkill 进程名 按进程名终止进程 pkill -9 sshd(终止所有 sshd 进程)

常用信号:-9(SIGKILL,强制终止)、-15(SIGTERM,优雅终止,默认)。

五、进程编程核心函数

5.1 fork():创建子进程

fork()是 Linux 创建进程的核心函数,作用是从当前进程(父进程)克隆一个子进程。

函数原型

c

运行

复制代码
#include <unistd.h>
pid_t fork(void);
核心特性
  • 一次调用,两次返回:父进程和子进程各返回一次;
  • 子进程是父进程的 "完全拷贝":复制父进程的 0-3G 用户空间、PCB(仅 PID 不同);
  • 执行起点:子进程从fork()函数的返回处开始执行;
  • 资源不共享:父子进程的变量、内存空间相互独立(写时复制);
  • 执行顺序:父子进程的运行顺序由内核调度决定,无法预测。
返回值
场景 返回值 说明
父进程中 fork 成功 >0(子进程的 PID) 可通过返回值区分父 / 子进程
子进程中 fork 成功 0 子进程无子进程,返回 0
fork 失败 -1 如资源不足、进程数超限
示例代码

c

运行

复制代码
#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t ret = fork();
    if (ret > 0) {
        // 父进程逻辑
        printf("父进程:PID=%d,子进程PID=%d\n", getpid(), ret);
    } else if (ret == 0) {
        // 子进程逻辑
        printf("子进程:PID=%d,父进程PID=%d\n", getpid(), getppid());
    } else {
        perror("fork失败");
        return 1;
    }
    return 0;
}

5.2 getpid():获取当前进程 PID

函数原型

c

运行

复制代码
#include <unistd.h>
pid_t getpid(void);
  • 功能:返回调用该函数的进程的 PID;
  • 参数:无;
  • 返回值:当前进程的 PID(非负整数)。

5.3 getppid():获取父进程 PID

函数原型

c

运行

复制代码
#include <unistd.h>
pid_t getppid(void);
  • 功能:返回调用该函数的进程的父进程 PID;
  • 参数:无;
  • 返回值:父进程的 PID(若父进程已终止,返回 1(init 进程))。

六、核心总结

  1. 进程是程序的动态执行过程,由 PCB 管理,占用系统资源,支持并发;
  2. 虚拟内存为进程提供隔离性和安全性,上下文切换是实现并发的核心机制;
  3. Linux 通过 CFS 等调度算法分配 CPU 时间片,实现 "宏观并行、微观串行";
  4. fork()是创建进程的核心函数,父子进程独立运行,返回值是区分二者的关键;
  5. ps/top/kill是进程管理的常用命令,getpid()/getppid()是获取进程 ID 的核心函数。
相关推荐
小坏讲微服务2 小时前
Spring Boot 4.0 整合 Kafka 企业级应用指南
java·spring boot·后端·kafka·linq
Amrf2 小时前
使用bootlin工具链制作交叉编译器
linux
Data_agent2 小时前
京东获得京东商品详情API,python请求示例
java·前端·爬虫·python
Amrf2 小时前
在ubuntu 20上面编译fakeroot 1.37
linux·运维·ubuntu
迈巴赫车主2 小时前
蓝桥杯 20531黑客java
java·开发语言·数据结构·算法·职场和发展·蓝桥杯
wanhengidc2 小时前
深度解析云手机与云真机的关系
运维·服务器·安全·智能手机·生活
weixin_471525782 小时前
【Win11+Ubuntu双系统安装】
linux·运维·ubuntu
林鸿群2 小时前
Android AOSP 15 源码Ubuntu编译
android·linux·ubuntu·aosp
ZePingPingZe2 小时前
Spring Boot常见注解
java·spring boot·后端