【Linux应用编程】深入理解Linux多任务机制:进程原理、状态转换与进程控制实战

1. 多任务与并发概述

在单核或多核处理器上,让操作系统具备同时处理多个任务 的能力称为多任务(Multitasking)

并发(Concurrency) :微观上单核 CPU 采用时间片轮询算法在多个任务之间快速切换,宏观上表现为多个任务"同时"执行。

并行(Parallelism):在多核 CPU 或多处理器系统中,不同的任务同时在不同的物理核心上真实地独立运行。

实现多任务的常见方式包括:多进程多线程

2. 深入理解 Linux 进程

2.1 进程与程序的区别

|--------------|---------------------|---------------------|
| 对比维度 | 程序(Program) | 进程(Process) |
| 概念定义 | 静态的数据指令集合 | 正在执行的程序 |
| 存储位置 | 外存/硬盘(如 a.out) | 内存 + CPU 寄存器 |
| 生命周期 | 永久存在 | 动态的,从启动到消亡 |
| 资源消耗 | 仅占用磁盘空间 | 消耗内存空间与 CPU 计算资源 |

核心结论进程是操作系统资源分配的最小单位

2.2 进程的 0-4G 内存布局

当一个进程被创建时,操作系统会为其分配一个 4G(32 位系统) 的虚拟地址空间,分为:

0 - 3G:用户空间(各个进程相互独立)

3G - 4G:内核空间(所有进程共享)

3. 进程的调度与状态转换

3.1 CPU 调度算法

操作系统内核通过调度器(Scheduler)分配 CPU 资源,常见的调度策略包括:

1.时间片轮询算法(Round-Robin)

2.先来先服务(FCFS) / 短作业优先(SJF)

3.高优先级优先算法(Priority Scheduling)

3.2 Linux 进程状态(七态模型)

在 Linux 中,进程在生命周期内会经历如下状态变迁:

|--------------|-------------------------------|--------------------------------|
| 状态代码 | 状态名称 | 详细说明 |
| R | Running / Runnable | 运行态/就绪态:正在 CPU 上运行或等待 CPU 调度 |
| S | Interruptible Sleep | 可中断睡眠态:阻塞等待资源(如等待键盘输入),可被信号唤醒 |
| D | Uninterruptible Sleep | 不可中断睡眠态:进程不响应信号打断(通常发生在驱动 I/O) |
| T | Stopped | 暂停态:收到 SIGSTOP 信号后暂停执行 |
| Z | Zombie | 僵尸态:进程已终止,但其资源尚未被父进程回收 |
| X | Dead | 消亡态:进程资源被彻底释放回收 |

4. 进程管理常用命令

在 Linux 终端中,可以使用以下命令查看与控制进程:

1.ps -aux :查看系统中所有进程的详细参数(PID、CPU/内存占用率、进程状态等)。

ps -aux | grep a.out

2.ps -ef:查看进程的树形父子关系(PID 与 PPID)。

3.top:动态实时查看进程状态与系统 CPU、内存占用率。

4.pstree -sp <PID>:查看指定 PID 进程的族谱/创建关系。

5.kill:给指定进程发送控制信号。

    • kill -l:查看系统支持的所有信号。
    • kill -9 <PID>:强制结束指定 PID 的进程。

6.jobs / fg:查看后台进程与将后台进程切换至前台。

5. 进程控制 API 实战

5.1 创建子进程 fork()

操作系统通过 fork() 创建新进程。fork() 调用完成后,系统会将父进程 0-3G 的用户空间完整拷贝一份给子进程(写时复制 Copy-On-Write 机制)。

#include <sys/types.h>

#include <unistd.h>

pid_t fork(void);

返回值

在父进程中 :返回创建成功的 子进程 PID(pid > 0)。

在子进程中 :固定返回 0(pid == 0)。

失败:返回 -1。

注意

1.父子进程共享 3G-4G 内核空间 ,但各自 0-3G 用户空间相互独立,不能直接通过共享全局变量进行通信。

2.获取进程 PID API:getpid() 获取当前进程 PID,getppid() 获取父进程 PID。

C语言代码实战:fork() 使用示例

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

int main(void) {

int num = 100;

printf("Before fork, PID = %d\n", getpid());

pid_t pid = fork();

if (pid < 0) {

perror("fork error");

return -1;

}

else if (pid == 0) {

// 子进程逻辑

num += 50;

printf("Child PID: %d, PPID: %d, num = %d\n", getpid(), getppid(), num);

}

else {

// 父进程逻辑

sleep(1); // 让子进程先运行

printf("Parent PID: %d, Child PID: %d, num = %d\n", getpid(), pid, num);

}

return 0;

}

5.2 进程的退出 exit()

进程退出的常见方式:

  1. main 函数中使用 return 退出。
  2. 调用标准 C 库函数 exit() 或系统调用 _exit() / _Exit()。
  3. 外部发送信号强行终止(如 kill -9 PID)。

#include <stdlib.h>

void exit(int status);

参数 status:0 表示正常退出;非 0 表示因异常或特定错误退出。

5.3 孤儿进程与僵尸进程处理

(1) 孤儿进程(Orphan Process)

定义 :父进程先退出,子进程仍在运行。子进程成为孤儿进程

处理机制 :孤儿进程会被系统顶级进程(init 或 systemd,PID=1)收养,子进程结束后由系统回收,不会造成系统资源泄露

(2) 僵尸进程(Zombie Process)

定义:子进程已经退出,但父进程没有调用 wait() / waitpid() 回收其内核空间资源(PCB)。

危害:过多僵尸进程会导致 PID 号被耗尽,系统无法创建新进程。

(3) 解决僵尸进程:wait() 与 waitpid()

父进程可以调用 wait() 或 waitpid() 阻塞/非阻塞等待子进程结束并回收其资源:

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait(int *wstatus);

C语言代码实战:wait() 回收子进程

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/wait.h>

int main(void) {

pid_t pid = fork();

if (pid < 0) {

perror("fork error");

return -1;

}

else if (pid == 0) {

// 子进程逻辑

printf("Child process running... PID: %d\n", getpid());

sleep(2);

exit(10); // 子进程带状态码 10 退出

}

else {

// 父进程逻辑

int status = 0;

printf("Parent process waiting for child...\n");

pid_t z_pid = wait(&status); // 阻塞等待并回收子进程

if (WIFEXITED(status)) {

printf("Child (PID: %d) exited with code: %d\n",

z_pid, WEXITSTATUS(status));

}

}

return 0;

}

6. 总结

1.进程 是 Linux 系统分配资源的基本单位,拥有独立 0-3G 用户空间,安全稳定。

2.使用 fork() 可以轻松创建多进程,父子进程通过返回值区分逻辑。

3.必须注意避免产生 僵尸进程 ,通过 wait() / waitpid() 显式回收子进程资源。

4.由于进程间用户内存空间隔离,实现多进程协同需进一步学习 IPC(进程间通信:管道、信号、共享内存、消息队列、信号量)

相关推荐
名字还没想好☜1 小时前
Python asyncio.Queue 实战:用生产者-消费者给爬虫/任务流限速又解耦
开发语言·爬虫·python·并发·asyncio
FORCECON11 小时前
力控SCADA工程升级:信创跨平台迁移方案,快速搭建安全自主的工业监控系统
linux·windows·自动化·信创·scada·监控组态软件
小义_1 小时前
Linux 性能排查实战
linux·服务器·php
玉树临风ives1 小时前
atcoder ABC 472 题解
数据结构·c++·算法
AI服务老曹1 小时前
抽烟识别算法接入 AI 视频分析平台的流程与误报优化指南
人工智能·算法·音视频
阳明山水1 小时前
销量预测2025—2026:技术演进、实证发现与系统架构的系统性综述
人工智能·深度学习·算法·机器学习·架构
伯远医学1 小时前
RIP-seq 高分文献案例分享
java·前端·javascript·人工智能·算法·eclipse·html
问君能有几多愁~2 小时前
Qt Json 序列化操作
开发语言·qt·json
xieliyu.2 小时前
MySQL 进阶笔记:用户 / 会话 / 全局 / 局部变量 + CASE 分支语法
开发语言·数据库·笔记·mysql