学习笔记——Linux 进程管理笔记

inux 进程管理笔记

一、父子进程关系

1. 进程复制机制

  • 子进程是父进程的副本

  • Linux 2.6之后(如Ubuntu 18,Linux 5.4) :采用**写时复制(Copy-On-Write,COW)**技术

  • fork完成后:子进程共享父进程的所有内存空间

  • 写时复制触发时机:当父子进程中的任何一方尝试修改某个变量或内存区域时,才会为子进程开辟新的内存空间

2. 进程终止的8种情况

正常终止:
  1. main函数中的return

  2. exit() - C库函数

    • 执行I/O库的清理工作

    • 关闭所有流和已打开的文件

    • 执行清理函数(atexit注册的函数)

  3. _exit() / _Exit() - 系统调用

    • 关闭所有已打开的文件

    • 不执行清理函数

  4. 主线程退出

  5. 主线程调用pthread_exit()

异常终止:
  1. abort() - 产生SIGABRT信号

  2. 信号终止 - signal/kill发送信号

  3. 最后一个线程被pthread_cancel()

二、进程退出后的状态

1. 僵尸进程(Zombie)

  • 产生条件:子进程先于父进程终止

  • 状态特征

    • 用户内存空间已释放

    • 进程不会被调度执行

    • 但内核中的PCB(进程控制块)未被释放

  • 危害:长时间运行的父进程多次创建子进程时,可能导致内核空间积累大量僵尸进程PCB,引发系统不稳定或崩溃

  • 查看命令pstop

2. 孤儿进程(Orphan)

  • 产生条件:父进程先于子进程终止

  • 处理机制

    • 子进程会被init进程(PID=1)接管

    • 由新的父进程(init)负责回收资源

    • 通常无需特别关注

三、退出函数详解

1. exit() - 库函数

复制代码
void exit(int status);
  • 功能:让进程退出,并刷新缓冲区

  • 参数

    • status:进程退出状态

    • 常用值:EXIT_SUCCESS(0)、EXIT_FAILURE(1)

  • 执行流程

    • 刷新缓冲区

    • 执行atexit()注册的退出函数

    • 调用_exit()系统调用

2. _exit() - 系统调用

复制代码
void _exit(int status);
  • 功能 :让进程退出,不刷新缓冲区

  • 参数status - 进程退出状态

3. return关键字的区别

  • 在main函数中:结束整个进程

  • 在其他函数中:仅结束当前函数

四、进程状态回收

1. wait()函数

复制代码
pid_t wait(int *status);
  • 功能:阻塞等待任意子进程退出,并回收其状态

  • 特点

    • 只能由父进程调用

    • 一次只能回收一个子进程

  • 参数

    • status:存储子进程退出状态

    • 不关心状态时可传入NULL

  • 返回值

    • 成功:回收的子进程PID

    • 失败:-1

2. 状态检查宏

功能 说明
WIFEXITED(status) 检查是否正常终止 返回非0表示正常结束
WEXITSTATUS(status) 获取退出状态值 正常终止时使用
WIFSIGNALED(status) 检查是否信号终止 返回非0表示信号终止
WTERMSIG(status) 获取终止信号编号 信号终止时使用

3. 使用示例

复制代码
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    pid_t pid = fork();
    
    if (pid == 0) {
        // 子进程
        exit(42);  // 正常退出,状态码42
    } else {
        // 父进程
        int status;
        wait(&status);
        
        if (WIFEXITED(status)) {
            printf("子进程正常退出,返回值:%d\n", 
                   WEXITSTATUS(status));  // 输出:42
        }
        if (WIFSIGNALED(status)) {
            printf("子进程被信号终止,信号:%d\n",
                   WTERMSIG(status));
        }
    }
    return 0;
}

五、进程空间回收的重要性

1. 僵尸进程的危害

  • 内核PCB空间被占用,无法释放

  • 大量僵尸进程可能导致内核内存不足

  • 影响系统稳定性和性能

2. 回收策略

  • 父进程应主动调用wait()waitpid()回收子进程

  • 对于需要多次创建子进程的服务进程,必须正确回收

  • 可使用信号处理函数(如SIGCHLD)异步回收

六、总结要点

  1. 写时复制是现代Linux的优化机制,减少不必要的内存复制

  2. 区分正常终止与异常终止的不同处理方式

  3. exit()和_exit()的主要区别在于缓冲区刷新和清理函数执行

  4. 僵尸进程需要父进程主动回收,否则会长期占用系统资源

  5. wait()系列函数是进程回收的标准方法

  6. 状态检查宏帮助父进程了解子进程的终止原因

注意事项

  • 在生产环境中,应确保所有子进程都被正确回收

  • 对于服务器程序,建议设置SIGCHLD信号处理

  • 使用waitpid()可以更灵活地控制回收行为(如非阻塞模式)

相关推荐
好奇龙猫1 小时前
【AI学习-comfyUI学习-第三十节-第三十一节-FLUX-SD放大工作流+FLUX图生图工作流-各个部分学习】
人工智能·学习
saoys1 小时前
Opencv 学习笔记:图像掩膜操作(精准提取指定区域像素)
笔记·opencv·学习
MM_MS1 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
C_心欲无痕1 小时前
ts - tsconfig.json配置讲解
linux·前端·ubuntu·typescript·json
独自破碎E1 小时前
【二分法】寻找峰值
算法
冰西瓜6002 小时前
国科大2025操作系统高级教程期末回忆版
linux
mit6.8242 小时前
位运算|拆分贪心
算法
电子小白1232 小时前
第13期PCB layout工程师初级培训-1-EDA软件的通用设置
笔记·嵌入式硬件·学习·pcb·layout
ghie90902 小时前
基于MATLAB的TLBO算法优化实现与改进
开发语言·算法·matlab
恋爱绝缘体12 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit