学习笔记——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()可以更灵活地控制回收行为(如非阻塞模式)

相关推荐
邵小的运维之路4 小时前
静态路由与 BFD 联动
运维·网络·智能路由器
lxmyzzs4 小时前
【图像算法 - 38】工业巡检应用:基于 YOLO 与 OpenCV 的高精度管道缺陷检测系统实现
opencv·算法·yolo·管道检测
老鱼说AI4 小时前
算法基础教学:哈希表
数据结构·算法·散列表
解局易否结局4 小时前
GitCode口袋工具开发学习
学习·gitcode
逐辰十七4 小时前
freertos学习笔记12--个人自用-第18章 资源管理(Resource Management)
笔记·学习
lxmyzzs4 小时前
【图像算法 - 39】环保监测应用:基于 YOLO 与 OpenCV 的高精度水面垃圾检测系统实现
opencv·算法·yolo·水下垃圾检测
点云SLAM4 小时前
Redundant 英文单词学习
人工智能·学习·英文单词学习·雅思备考·redundant·冗余的·多余的 、重复的
linsa_pursuer4 小时前
回文链表算法
java·算法·链表
free-elcmacom4 小时前
机器学习进阶<13>基于Boosting集成算法的信用评分卡模型构建与对比分析
python·算法·机器学习·boosting