当前位置: 首页 > news >正文

嵌入式学习Day28

进程的退出:

僵尸进程(Zombie Process)

僵尸进程是指子进程已经终止,但其父进程尚未通过wait()waitpid()系统调用获取其退出状态信息。此时,子进程的进程描述符仍保留在系统中,但不再占用CPU资源。僵尸进程会占用少量系统资源(如PID),大量僵尸进程可能导致系统无法创建新进程。

特点

  • 进程已终止,但进程表项未释放。
  • 父进程未正确处理子进程的退出状态。

解决方法

  • 父进程调用wait()waitpid()主动回收子进程资源。
  • 若父进程不处理,可通过终止父进程(僵尸进程会被init进程接管并回收)。

孤儿进程(Orphan Process)

孤儿进程是指父进程先于子进程终止,子进程被init进程(PID=1)接管。孤儿进程不会占用系统资源,因为init进程会定期调用wait()回收它们。

特点

  • 父进程已终止,子进程由init接管。
  • 不会成为僵尸进程,因为init会自动回收。

关键区别

特征僵尸进程孤儿进程
父进程状态仍在运行但未调用wait()已终止
处理方式需父进程主动回收init进程自动回收
资源占用占用PID不占用资源

如何避免

  • 避免僵尸进程:父进程应注册SIGCHLD信号处理函数或使用waitpid()非阻塞调用。
  • 孤儿进程无需处理:系统会自动管理。

exit 函数概述

在 Linux 系统中,exit 是一个用于终止进程的系统调用或库函数。它属于标准 C 库(stdlib.h),也可通过系统调用直接使用。调用 exit 会结束当前进程,并返回一个状态码给父进程。


exit 函数原型

标准 C 库中的 exit 函数原型如下:

#include <stdlib.h>
void exit(int status);
  • status:进程的退出状态码。通常 0 表示成功,非零值表示错误(具体含义由程序定义)。

系统调用层面的 exit

在 Linux 系统调用中,exit 对应的系统调用是 _exit 原型如下:

#include <unistd.h>
void _exit(int status);
  • _exit:直接终止进程,不执行标准库的清理操作(如刷新缓冲区、调用 atexit 注册的函数等)。

exit 与 _exit 的区别

  1. 标准库函数 exit

    • 会调用通过 atexit 注册的函数。
    • 刷新标准 I/O 缓冲区(如 printf 的输出)。全面的回收工作,文件关闭、堆释放,缓冲区清理。
    • 最终调用 _exit 系统调用。
  2. 系统调用 _exit

    • 立即终止进程,不执行任何清理操作。不刷新缓存区。只会关闭打开的文件。
    • 适用于子进程或需要快速退出的场景。

退出状态码的约定

  • 0:成功退出。
  • 非零值:通常表示错误,具体含义由程序定义。

atexit 函数概述

atexit 是 Linux/Unix 系统中的一个标准库函数,用于注册程序正常终止时要调用的函数。这些函数会在程序通过 exit 或从 main 函数返回时执行,通常用于资源清理、日志记录等收尾工作。

函数原型

#include <stdlib.h>
int atexit(void (*function)(void));
  • 参数function 是一个无参数、无返回值的函数指针。
  • 返回值: 成功返回 0,失败返回非零。

结果为aaaa  bbb  cccc。

关键特性

  • 执行顺序: 后注册的函数先执行(LIFO 顺序)。
  • 调用场景: 仅在程序正常终止时触发,通过 exit 或 main 返回。强制终止(如 kill 或 abort)不会触发。
  • 限制: 标准要求至少支持 32 个函数的注册,实际可通过 sysconf(_SC_ATEXIT_MAX) 查询。

注意事项

  • 避免在退出函数中调用 exit 或依赖已释放的资源。
  • 线程安全性问题需考虑,atexit 在多线程环境中的行为需结合实现细节。
  • 使用atexit时只能调用exit。

典型应用场景

  1. 关闭文件描述符或释放动态内存。
  2. 持久化程序状态或日志收尾。
  3. 临时文件清理。

wait函数概述

wait函数在Linux中用于父进程等待子进程的状态变化(如终止或停止)。它是进程间同步的重要工具,属于系统调用的一部分,定义在<sys/wait.h>头文件中。

基本语法

#include <sys/wait.h>
pid_t wait(int *status);
  • 参数status是一个指针,用于存储子进程的退出状态信息。若不需要状态信息,可传入NULL
  • 返回值:成功时返回终止的子进程PID,失败时返回-1

功能详解

  1. 阻塞等待:调用wait时,父进程会阻塞直到任一子进程终止。(一个wait回收一个子进程)
  2. 状态信息:通过status可获取子进程退出原因(如正常退出、信号终止等)。需使用宏(如WIFEXITEDWEXITSTATUS)解析状态值。

注意事项

  • 若父进程无子进程,wait会立即返回-1,并设置errnoECHILD
  • 多个子进程时,wait按任意顺序返回一个终止的子进程状态。需循环调用以等待所有子进程。

waitpid 函数概述

waitpid 是 Linux/Unix 系统中用于等待子进程状态变化的系统调用。它允许父进程暂停执行,直到指定的子进程终止或收到信号。相比于 waitwaitpid 提供了更精确的控制,例如可以指定等待的子进程 PID 或通过选项调整行为。

函数原型

#include <sys/types.h>
#include <sys/wait.h>pid_t waitpid(pid_t pid, int *status, int options);
  • pid: 指定等待的子进程 PID:
    • >0: 等待特定 PID 的子进程。
    • -1: 等待任意子进程(类似 wait)。
    • 0: 等待与调用进程同组的任意子进程。
    • <-1: 等待进程组 ID 等于 |pid| 的任意子进程。
  • status: 输出参数,存储子进程的退出状态(可通过宏如 WIFEXITED 解析)。
  • options: 控制行为,常用选项:
    • WNOHANG: 非阻塞模式,无子进程退出时立即返回。
    • WUNTRACED: 报告已停止的子进程状态(即使未终止)。

返回值

  • 成功: 返回状态变化的子进程 PID。
  • 错误: 返回 -1(如无匹配子进程或信号中断),并设置 errno

关键宏解析

  • WIFEXITED(status): 子进程正常退出时返回真。
  • WEXITSTATUS(status): 提取子进程退出码(需 WIFEXITED 为真)。
  • WIFSIGNALED(status): 子进程因信号终止时返回真。
  • WTERMSIG(status): 提取终止信号的编号(需 WIFSIGNALED 为真)。

注意事项

  • 阻塞行为: 默认情况下(options=0),waitpid 会阻塞直到目标子进程状态变化。使用 WNOHANG 可避免阻塞。
  • 僵尸进程: 未调用 waitpid 的父进程可能导致子进程成为僵尸进程(保留退出状态直到父进程读取)。
  • 信号处理: 若信号中断了 waitpid,需检查 errno 是否为 EINTR 并决定是否重试。

execl 函数

execl 用于执行指定路径的程序,参数以列表形式传递。

#include <unistd.h>
int execl(const char *path, const char *arg0, ..., (char *) NULL);
  • path:可执行文件的完整路径。
  • arg0:程序名(通常与 argv[0] 一致),后续为命令行参数,以 NULL 结尾。

execlp 函数

execlp 在 execl 基础上自动搜索 PATH 环境变量中的目录。

int execlp(const char *file, const char *arg0, ..., (char *) NULL);
  • file:程序名(如 ls),系统会从 PATH 中查找可执行文件。

execvp 函数

execvp 结合了参数数组和 PATH 搜索功能。

int execvp(const char *file, char *const argv[]);
  • file:程序名,通过 PATH 查找。
  • argv:参数数组,以 NULL 结尾。

区别总结

函数路径处理参数传递方式
execl需完整路径参数列表
execlp自动搜索 PATH参数列表
execvp自动搜索 PATH参数数组

所有函数成功时替换当前进程映像,失败返回 -1 并设置 errno

相关文章:

  • 移动端H5拍照直传不落地方案
  • 2025.5.26 关于后续更新内容的通知
  • 语音识别技术在人工智能中的应用
  • 【C++进阶篇】初识哈希
  • 公共字段自动填充功能实现【springboot】
  • USB设备状态
  • js-day2
  • docker-compose 环境下备份数据库
  • [灵龙AI API] AI生成视频API:文生视频 – 第2篇
  • 爬虫IP代理效率优化:策略解析与实战案例
  • Rk3568驱动开发_设备树点亮LED_11
  • 剑指offer11_矩阵中的路径
  • AI时代新词-零样本学习(Zero-Shot Learning):AI的未来趋势
  • 4 通道1250MSPS‐16bit DAC 回放板
  • IPD流程落地:项目任务书Charter开发
  • MQTT通信协议
  • Guard Trace 值得吗?
  • ASP.NET Core OData 实践——Lesson2增删改查Entity和EntitySet(C#)
  • 基于Qlearning强化学习的二阶弹簧动力学模型PID控制matlab性能仿真
  • OSC协议简介、工作原理、特点、数据的接收和发送
  • bootstrap 网站模板 下载/seo数据分析哪些方面
  • 南京做网站哪家公司最好/竞价账户托管的公司有哪些
  • 营销网站开发哪家强/下载百度app最新版并安装
  • 石家庄哪里做微网站/电商网站项目
  • 建一个国外网站多少钱/厦门网
  • 帮企网站建设代运营/郑州seo外包费用