嵌入式Linux:如何监视子进程

目录

1、wait()函数

2、waitpid()函数

3、SIGCHLD信号


在嵌入式Linux系统中,父进程通常需要创建子进程来执行特定任务,例如处理网络请求、执行计算任务等。监视子进程的状态不仅可以确保资源的合理利用,还能防止僵尸进程的产生,从而提升系统的稳定性和性能。wait()waitpid()是用于监视和管理子进程的关键系统调用,而SIGCHLD信号则提供了一种异步通知机制,以便父进程在子进程状态发生变化时采取相应的措施。

1、wait()函数

wait()系统调用用于让父进程等待任意一个子进程的终止,并获取该子进程的终止状态信息。它执行以下功能:

  • 等待子进程终止:父进程在调用wait()后会阻塞,直到其任意一个子进程终止为止。
  • 回收子进程资源:当子进程终止时,操作系统需要回收它占用的资源,这一过程称为“收尸”。如果不进行回收,子进程会变为僵尸进程,占用系统资源。

僵尸进程是已经终止,但父进程尚未读取其终止状态的子进程。通过调用wait()可以避免系统中积累僵尸进程,影响性能和稳定性。

函数原型如下:

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);

参数与返回值:

  • status:这是一个指向int的指针,用于存储子进程的退出状态。父进程可以通过这个状态了解子进程是正常退出还是被信号中止的。如果传入NULL,则表示不关心子进程的退出状态,仅仅是等待它终止。

  • 返回值:返回已终止的子进程的进程ID;如果调用时没有子进程存在,wait()返回-1,并将errno设为ECHILD表示没有子进程可等待。

函数行为:

  • 阻塞等待wait()会阻塞调用进程,直到任意一个子进程终止。如果所有子进程都还在运行,wait()将持续阻塞。
  • 资源回收:当子进程终止时,wait()除了获取子进程的终止状态,还会回收子进程的资源,避免产生僵尸进程。
  • 处理已终止的子进程:如果wait()调用时有子进程已终止,函数将立即返回,而不会阻塞。

状态检查:

使用宏可以检查和处理status参数中存储的子进程终止状态:

  • WIFEXITED(status):如果子进程是通过exit()_exit()正常终止的,则返回true

  • WEXITSTATUS(status):当WIFEXITED(status)true时,可以通过该宏获取子进程的退出状态,通常是子进程在调用exit()_exit()时的退出码。

  • WIFSIGNALED(status):如果子进程因接收到某个信号而异常终止,则返回true

  • WTERMSIG(status):当WIFSIGNALED(status)true时,可以通过该宏获取导致子进程终止的信号编号。

  • WIFSTOPPED(status):如果子进程处于暂停状态,则返回true

  • WSTOPSIG(status):当WIFSTOPPED(status)true时,可以获取导致子进程暂停的信号编号。

  • WCOREDUMP(status):如果子进程终止时生成了核心转储文件,则返回true

以下示例展示了如何使用wait()函数来监视子进程的终止状态。

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {pid_t pid = fork();  // 创建子进程if (pid == -1) {// fork()失败perror("fork failed");exit(EXIT_FAILURE);} else if (pid == 0) {// 子进程执行代码printf("Child process running (PID: %d)...\n", getpid());sleep(2);  // 模拟子进程的执行exit(42);  // 正常退出,并返回状态码42} else {// 父进程执行代码int status;pid_t child_pid = wait(&status);  // 等待任一子进程终止if (child_pid > 0) {// 子进程终止后的处理if (WIFEXITED(status)) {printf("Child process %d terminated with status: %d\n", child_pid, WEXITSTATUS(status));} else if (WIFSIGNALED(status)) {printf("Child process %d was terminated by signal: %d\n", child_pid, WTERMSIG(status));}} else {perror("wait failed");}}return 0;
}

在这段代码中,父进程创建了一个子进程并等待其终止,同时通过status宏获取子进程的退出状态。

wait()函数的局限性:

  • 无法指定特定子进程wait()无法让父进程选择等待某个特定的子进程,它只能按顺序等待下一个终止的子进程。如果父进程同时拥有多个子进程,wait()将随机处理任意一个子进程的终止。

  • 阻塞等待wait()始终是阻塞的,直到有子进程终止为止。如果父进程需要继续处理其他任务,则wait()的阻塞可能导致父进程效率低下。

2、waitpid()函数

waitpid()函数提供了更多的控制选项,使得父进程可以选择性地等待某个特定子进程,或进行非阻塞的等待。

函数原型如下:

#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);

参数:

  • pid:指定需要等待的子进程:
    • > 0:等待指定PID的子进程。
    • = 0:等待与调用进程同一进程组的任意子进程。
    • < -1:等待进程组ID等于pid绝对值的所有子进程。
    • = -1:等待任意子进程,与wait()等价。
  • status:与wait()status参数相同。
  • options:可以设置为0或包含以下标志:
    • WNOHANG:非阻塞模式。如果没有子进程终止,立即返回0
    • WUNTRACED:返回因信号停止的子进程的状态。
    • WCONTINUED:返回收到SIGCONT信号后恢复运行的子进程的状态。

返回值:

  • 成功时,返回已终止或状态已改变的子进程的PID。
  • 如果没有符合条件的子进程,且设置了WNOHANG选项,返回0
  • 失败时返回-1,并设置errno

waitpid()wait()的区别:

  • 等待特定子进程waitpid()允许父进程通过pid参数指定特定的子进程,而wait()只能等待任意子进程。
  • 非阻塞模式waitpid()支持非阻塞模式(通过WNOHANG),使父进程可以立即返回,而不必等待子进程终止。
  • 支持更多状态监控waitpid()可以监视子进程暂停(WUNTRACED)或恢复运行(WCONTINUED)的状态,而wait()无法做到这一点。

示例代码:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {pid_t pid = fork();  // 创建子进程if (pid == -1) {// fork()失败perror("fork failed");exit(EXIT_FAILURE);} else if (pid == 0) {// 子进程执行代码printf("Child process running (PID: %d)...\n", getpid());sleep(2);  // 模拟子进程工作exit(42);  // 正常退出,返回状态码42} else {// 父进程执行代码int status;pid_t child_pid;// 非阻塞等待子进程do {child_pid = waitpid(pid, &status, WNOHANG);  // 非阻塞模式if (child_pid == 0) {printf("No child process terminated yet. Doing other work...\n");sleep(1);  // 模拟其他工作} else if (child_pid > 0) {if (WIFEXITED(status)) {printf("Child process %d terminated with status: %d\n", child_pid, WEXITSTATUS(status));} else if (WIFSIGNALED(status)) {printf("Child process %d was terminated by signal: %d\n", child_pid, WTERMSIG(status));}} else {perror("waitpid failed");exit(EXIT_FAILURE);}} while (child_pid == 0);printf("Parent process continues...\n");}return 0;
}

在这个示例中,父进程可以继续处理其他任务,而不必一直阻塞等待子进程的终止。waitpid()的非阻塞模式使得程序更为灵活和高效。 

3、SIGCHLD信号

SIGCHLD是父进程在子进程状态发生变化(如终止或暂停)时收到的信号。通过捕获SIGCHLD信号,父进程可以实时地检测到子进程的状态变化,并采取相应的行动(例如回收资源)。

在POSIX标准下,sigaction()系统调用被广泛用于设置信号处理程序。相比于传统的signal()函数,sigaction()提供了更多的选项和更好的控制。

示例代码:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>void sigchld_handler(int signum) {int status;pid_t pid;// 循环调用waitpid,以确保处理多个已终止的子进程while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {if (WIFEXITED(status)) {printf("Child process %d terminated with status: %d\n", pid, WEXITSTATUS(status));} else if (WIFSIGNALED(status)) {printf("Child process %d was terminated by signal: %d\n", pid, WTERMSIG(status));}}
}int main() {struct sigaction sa;sa.sa_handler = sigchld_handler;  // 指定信号处理函数sigemptyset(&sa.sa_mask);  // 清空阻塞信号集sa.sa_flags = SA_RESTART;  // 自动重启被中断的系统调用sigaction(SIGCHLD, &sa, NULL);  // 安装信号处理程序for (int i = 0; i < 3; i++) {pid_t pid = fork();  // 创建多个子进程if (pid == 0) {// 子进程代码printf("Child process %d running...\n", getpid());sleep(2);exit(42);}}// 父进程的其他工作while (1) {printf("Parent process working...\n");sleep(1);}return 0;
}

使用sigaction()的优点:

  • 自动重启:通过设置SA_RESTART标志,能够在信号处理完成后自动重启被中断的系统调用(如read()write())。
  • 可靠的信号处理sigaction()避免了传统signal()函数的缺陷,确保了信号处理的可靠性和可移植性。

SIGCHLD信号的常见问题与解决方案:

  • 丢失信号:在同时终止多个子进程时,可能会丢失一些SIGCHLD信号。为解决这一问题,可以在信号处理程序中循环调用waitpid(),直到没有子进程终止为止。
  • 阻塞的系统调用:信号处理可能会中断一些阻塞的系统调用(如read()sleep()),导致它们返回错误。通过使用sigaction()SA_RESTART标志可以自动重启被中断的调用。

通过以上内容,开发者可以根据实际需求选择合适的方法来监视和管理子进程,确保程序运行的稳定性和资源的有效利用。

  • 如果只需等待任意一个子进程终止且不关心特定子进程,使用wait()是最简单的选择。
  • 如果需要非阻塞地等待特定子进程或需要获取更多子进程状态信息,waitpid()则更为灵活。
  • 在处理多个子进程时,捕获SIGCHLD信号可以让父进程更加实时地处理子进程的终止,并在不中断父进程正常操作的情况下回收子进程资源。

无论是使用wait()waitpid()还是SIGCHLD信号处理,确保及时回收子进程的资源是避免僵尸进程的关键。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/68498.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「 机器人 」扑翼飞行器控制策略浅谈

1. 研究背景 • 自然界中的蜂鸟以极高的机动能力著称,能够在短至0.2秒内完成如急转弯、快速加速、倒飞、躲避威胁等极限机动。这种表现对微型飞行器(Flapping Wing Micro Air Vehicles, FWMAVs)具有重要的仿生启示。 • 目前的微型飞行器距离自然生物的飞行能力仍有相当差距…

渗透测试之WAF规则触发绕过规则之规则库绕过方式

目录 Waf触发规则的绕过 特殊字符替换空格 实例 特殊字符拼接绕过waf Mysql 内置得方法 注释包含关键字 实例 Waf触发规则的绕过 特殊字符替换空格 用一些特殊字符代替空格&#xff0c;比如在mysql中%0a是换行&#xff0c;可以代替空格 这个方法也可以部分绕过最新版本的…

c++ map/multimap容器 学习笔记

1 map的基本概念 简介&#xff1a; map中所有的元素都是pair pair中第一个元素是key&#xff08;键&#xff09;&#xff0c;第二个元素是value&#xff08;值&#xff09; 所有元素都会根据元素的键值自动排序。本质&#xff1a; map/multimap 属于关联式容器&#xff0c;底…

深入理解若依RuoYi-Vue数据字典设计与实现

深入理解若依数据字典设计与实现 一、Vue2版本主要文件目录 组件目录src/components&#xff1a;数据字典组件、字典标签组件 工具目录src/utils&#xff1a;字典工具类 store目录src/store&#xff1a;字典数据 main.js&#xff1a;字典数据初始化 页面使用字典例子&#xf…

PyTorch 与 Python 版本对应关系

PyTorch 支持多个 Python 版本&#xff0c;但不同版本的 PyTorch 可能对 Python 版本有不同的要求。一般来说&#xff1a; PyTorch 与 Python 版本对应关系 PyTorch 版本支持的 Python 版本2.2.x3.8 - 3.122.1.x3.8 - 3.112.0.x3.8 - 3.101.13.x3.7 - 3.101.12.x3.7 - 3.101.…

JavaScript系列(47)--音频处理系统详解

JavaScript音频处理系统详解 &#x1f3b5; 今天&#xff0c;让我们深入探讨JavaScript的音频处理系统。Web Audio API为我们提供了强大的音频处理和合成能力&#xff0c;让我们能够在浏览器中实现复杂的音频应用。 音频系统基础概念 &#x1f31f; &#x1f4a1; 小知识&…

FortiOS 存在身份验证绕过导致命令执行漏洞(CVE-2024-55591)

免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…

Linux网络之TCP

Socket编程--TCP TCP与UDP协议使用的套接字接口比较相似, 但TCP需要使用的接口更多, 细节也会更多. 接口 socket和bind不仅udp需要用到, tcp也需要. 此外还要用到三个函数: 服务端 1. int listen(int sockfd, int backlog); 头文件#include <sys/socket.h> 功能: …

GIS与相关专业软件汇总

闲来无事突然想整理一下看看 GIS及相关领域 究竟有多少软件或者工具包等。 我询问了几个AI工具并汇总了一个软件汇总&#xff0c;不搜不知道&#xff0c;一搜吓一跳&#xff0c;搜索出来了大量的软件&#xff0c;大部分软件或者工具包都没有见过&#xff0c;不知大家还有没有要…

(四)线程 和 进程 及相关知识点

目录 一、线程和进程 &#xff08;1&#xff09;进程 &#xff08;2&#xff09;线程 &#xff08;3&#xff09;区别 二、串行、并发、并行 &#xff08;1&#xff09;串行 &#xff08;2&#xff09;并行 &#xff08;3&#xff09;并发 三、爬虫中的线程和进程 &am…

学历赋

崇岳北峙&#xff0c;紫气东临&#xff1b;学海横流&#xff0c;青云漫卷。连九陌而贯八荒&#xff0c;纳寒门而载贵胄。墨池泛舟&#xff0c;曾照匡衡凿壁之光&#xff1b;杏坛飞絮&#xff0c;犹闻仲尼弦歌之音。然观当下&#xff0c;黉宇接天如笋立&#xff0c;青衫叠浪似云…

支持selenium的chrome driver更新到132.0.6834.110

最近chrome释放新版本&#xff1a;132.0.6834.110 如果运行selenium自动化测试出现以下问题&#xff0c;是需要升级chromedriver才可以解决的。 selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only s…

python爬虫入门(一) - requests库与re库,一个简单的爬虫程序

目录 web请求与requests库 1. web请求 1.1 客户端渲染与服务端渲染 1.2 抓包 1.3 HTTP状态代码 2. requests库 2.1 requests模块的下载 2.2 发送请求头与请求参数 2.3 GET请求与POST请求 GET请求的例子&#xff1a; POST请求的例子&#xff1a; 3. 案例&#xff1a;…

Luzmo 专为SaaS公司设计的嵌入式数据分析平台

Luzmo 是一款嵌入式数据分析平台&#xff0c;专为 SaaS 公司设计&#xff0c;旨在通过直观的可视化和快速开发流程简化数据驱动决策。以下是关于 Luzmo 的详细介绍&#xff1a; 1. 背景与定位 Luzmo 前身为 Cumul.io &#xff0c;专注于为 SaaS 公司提供嵌入式分析解决方案。…

在虚拟机里运行frida-server以实现对虚拟机目标软件的监测和修改参数(一)(android Google Api 35高版本版)

frida-server下载路径 我这里选择较高版本的frida-server-16.6.6-android-x86_64 以root身份启动adb 或 直接在android studio中打开 adb root 如果使用android studio打开的话&#xff0c;最好选择google api的虚拟机&#xff0c;默认以root模式开启 跳转到下载的frida-se…

Excel - Binary和Text两种Compare方法

Option Compare statement VBA里可以定义默认使用的compare方法&#xff1a; Set the string comparison method to Binary. Option Compare Binary That is, "AAA" is less than "aaa". Set the string comparison method to Text. Option Compare Tex…

C#编译报错: error CS1069: 未能在命名空间“System.Windows.Markup”中找到类型名“IComponentConnector”

文章目录 问题现象解决方案 问题现象 一个以前使用.NET Framwork 3.0框架开发的项目&#xff0c;在框架升级到.NET Framwork 4.7.2后&#xff0c; 如下代码&#xff1a; #pragma checksum "..\..\XpsViewer.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}&qu…

能源新动向:智慧能源平台助力推动新型电力负荷管理系统建设

背景 国家能源局近日发布《关于支持电力领域新型经营主体创新发展的指导意见》&#xff0c;鼓励支持具备条件的工业企业、工业园区等开展智能微电网建设&#xff0c;通过聚合分布式光伏、分散式风电、新型储能、可调节负荷等资源&#xff0c;为电力系统提供灵活调节能力&#x…

用WinForm如何制作简易计算器

首先我们要自己搭好页面 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace _7_简易计算…

论文笔记(六十三)Understanding Diffusion Models: A Unified Perspective(四)

Understanding Diffusion Models: A Unified Perspective&#xff08;四&#xff09; 文章概括学习扩散噪声参数&#xff08;Learning Diffusion Noise Parameters&#xff09;三种等效的解释&#xff08;Three Equivalent Interpretations&#xff09; 文章概括 引用&#xf…