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

相关推荐
VkN2X2X4b31 分钟前
算法性能的渐近与非渐近行为对比的技术9
算法
好家伙VCC35 分钟前
**神经编码新视角:用Python实现生物启发的神经信号压缩与解码算法**在人工智能飞速发展的今天
java·人工智能·python·算法
@小匠5 小时前
Read Frog:一款开源的 AI 驱动浏览器语言学习扩展
人工智能·学习
qwy7152292581637 小时前
1-Docker Engine 安装前置环境配置
运维·docker·容器
W23035765738 小时前
经典算法:最长上升子序列(LIS)深度解析 C++ 实现
开发语言·c++·算法
菜菜艾8 小时前
基于llama.cpp部署私有大模型
linux·运维·服务器·人工智能·ai·云计算·ai编程
重生的黑客8 小时前
Linux开发工具:条件编译、动静态库与 make/makefile 入门
linux·运维·服务器
minji...9 小时前
Linux 线程同步与互斥(三) 生产者消费者模型,基于阻塞队列的生产者消费者模型的代码实现
linux·运维·服务器·开发语言·网络·c++·算法
.柒宇.9 小时前
nginx入门教程
运维·nginx
w6100104669 小时前
cka-2026-ConfigMap
java·linux·cka·configmap