06 - 深入Linux进程

---- 整理自狄泰软件唐佐林老师课程

查看所有文章链接:(更新中)Linux系统编程训练营 - 目录

文章目录

  • 1. 问题
    • 1.1 进程参数和环境变量的意义
    • 1.2 思考
  • 2. 深入理解父子进程
    • 2.1 进程等待系统接口
    • 2.2 进程退出系统接口
    • 2.3 问题
    • 2.4 进程退出状态详解
    • 2.5 僵尸进程(僵死状态)
    • 2.6 僵尸进程的危害
    • 2.7 wait()的局限
    • 2.8 编程实验:子进程实验
    • 2.9 僵尸进程避坑指南

1. 问题

  • 进程参数和环境变量对于进程意味着什么?

1.1 进程参数和环境变量的意义

  • 一般情况下,子进程的创建是为了解决某个子问题
  • 子进程解决问题需要父进程的 “数据输入”(进程参数 & 环境变量)
  • 设计原则:
    • 子进程启动时 必然 用到的参数使用 进程参数 传递
    • 子进程解决问题 可能 用到的参数使用 环境变量 传递

在这里插入图片描述

1.2 思考

  • 子进程如何将结果 “返回” 父进程?

06 - 深入Linux进程_第1张图片

【参看链接】:06 - 深入Linux进程 / 00 / test.c

06 - 深入Linux进程_第2张图片
06 - 深入Linux进程_第3张图片

2. 深入理解父子进程

  • 子进程的创建是为了 并行的解决子问题(问题分解,原问题分解为子问题,子问题之间没有依赖关系)
  • 父进程需要通过 等待子进程的结果 以最终解决问题(并获取结果)

06 - 深入Linux进程_第4张图片

2.1 进程等待系统接口

  • pid_t wait(int* status);
    • 等待一个子进程完成,并返回子进程标识和状态信息
    • 当有多个子进程完成,随机挑选一个子进程返回
  • pid_t waitpid(pid_t pid, int* status, int options);
    • 可等待特定的子进程或一组子进程
    • 在子进程还未终止时,可通过options设置不必等待(直接返回)

2.2 进程退出系统接口

  • 头文件:#include
    • void _exit(int status); // 系统调用,终止当前进程
  • 头文件:#include
    • void exit(int status); // 库函数,先做资源清理,再通过系统调用终止进程
    • void abort(void); // 异常终止当前进程(通过产生SIGABRT信号终止)
  • 注:信号:操作系统发送给进程的通知。

2.3 问题

下面的程序运行后会发生什么?

【参看链接】:06 - 深入Linux进程 / 01 / main.c

06 - 深入Linux进程_第5张图片
06 - 深入Linux进程_第6张图片

2.4 进程退出状态详解

06 - 深入Linux进程_第7张图片
06 - 深入Linux进程_第8张图片

  • 编程实验

【参看链接】:06 - 深入Linux进程 / 02 / main.c

06 - 深入Linux进程_第9张图片
06 - 深入Linux进程_第10张图片

2.5 僵尸进程(僵死状态)

【参看链接】:06 - 深入Linux进程 / 03 / main.c

06 - 深入Linux进程_第11张图片

  • 理论上,进程 退出 / 终止 后应立即释放所有系统资源
    • 然而,为了给父进程提供一些 重要信息,子进程 退出 / 终止 所占的部分资源 会暂留
    • 当父进程收集这部分信息后(wait / waitpid),子进程所有资源被释放
      • 父进程调用wait(),为子进程 “收尸” 处理并释放暂留资源
      • 若父进程退出,init / systemd 为子进程 “收尸” 处理并释放暂留资源

2.6 僵尸进程的危害

  • 僵尸进程保留进程的终止状态和资源的使用信息
    • 进程为何退出,进程消耗多少CPU时间,进程最大内存驻留值,等
  • 如果僵尸进程得不到回收,那么可能影响正常进程的创建
    • 进程创建最重要的资源是内存和进程标识
    • 僵尸进程的存在可看作是一种类型的内存泄露
    • 当系统僵尸进程过多,可能导致进程标识不足,无法创建新进程

2.7 wait()的局限

  • 不能等待指定子进程,如果存在多个子进程,只能逐一等待完成
  • 如果不存在终止的子进程,父进程只能阻塞等待
  • 只针对终止的进程,无法发现暂停的进程
  • wait(…)升级 ==> pid_t waitpid(pid_t pid, int* status, int options)
    • 返回值相同,终止子进程标识符
    • 状态值意义相同,记录子进程中止信息
    • 特殊之处:
      06 - 深入Linux进程_第12张图片

2.8 编程实验:子进程实验

【参看链接】:06 - 深入Linux进程 / 04/ main.c

06 - 深入Linux进程_第13张图片
06 - 深入Linux进程_第14张图片
06 - 深入Linux进程_第15张图片

2.9 僵尸进程避坑指南

  • 利用wait(…)返回值判断是否继续等待子进程,意味着 父进程阻塞
    • while( ( pid = wait(&status) ) > 0 ) { … }
  • 利用 waitpid(…)及 init / systemd 回收子进程
    • 通过两次fork()创建 孙进程 解决子问题

你可能感兴趣的:(Linux系统编程训练营,linux,unix,ubuntu,c语言,gnu)