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

新疆网站优化网站提交收录软件

新疆网站优化,网站提交收录软件,淘宝运营的基础知识,真人性做爰网站1. 理解子进程终止的机制 在Unix/Linux系统中,当子进程终止时,会向父进程发送一个SIGCHLD信号。父进程需要捕捉这个信号,并通过调用wait()或waitpid()等函数来回收子进程的资源。这一过程被称为“回收僵尸进程”。 如果父进程没有及时调用w…

1. 理解子进程终止的机制

在Unix/Linux系统中,当子进程终止时,会向父进程发送一个SIGCHLD信号。父进程需要捕捉这个信号,并通过调用wait()waitpid()等函数来回收子进程的资源。这一过程被称为“回收僵尸进程”。

如果父进程没有及时调用wait()或相关函数,子进程将会成为僵尸进程,占用系统资源,直到父进程终止或调用相应的等待函数。

2. 使用wait()waitpid()函数

  • wait():使父进程阻塞,直到任一子进程终止。它会返回终止子进程的PID,并存储子进程的退出状态。
  • waitpid():提供更精细的控制,可以等待特定的子进程或采用非阻塞方式。
例子:阻塞等待子进程终止
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main() {pid_t pid = fork();  // 创建子进程if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;}else if (pid == 0) {// 子进程执行的代码std::cout << "子进程PID:" << getpid() << " 启动。" << std::endl;sleep(2);  // 模拟子进程工作std::cout << "子进程PID:" << getpid() << " 结束。" << std::endl;return 42;  // 子进程以状态42退出}else {// 父进程执行的代码std::cout << "父进程PID:" << getpid() << " 等待子进程结束。" << std::endl;int status;pid_t terminated_pid = wait(&status);  // 阻塞等待任一子进程结束if (terminated_pid > 0) {if (WIFEXITED(status)) {std::cout << "子进程PID:" << terminated_pid << " 以状态 " << WEXITSTATUS(status) << " 退出。" << std::endl;}else if (WIFSIGNALED(status)) {std::cout << "子进程PID:" << terminated_pid << " 被信号 " << WTERMSIG(status) << " 终止。" << std::endl;}}else {std::cerr << "等待子进程失败。" << std::endl;}}return 0;
}

输出示例:

父进程PID:12345 等待子进程结束。
子进程PID:12346 启动。
子进程PID:12346 结束。
子进程PID:12346 以状态 42 退出。

代码解释:

  1. 父进程调用fork()创建子进程。
  2. 子进程执行自己的任务后,以状态42退出。
  3. 父进程调用wait()阻塞等待子进程结束,并获取子进程的退出状态。
  4. 父进程通过宏WIFEXITEDWEXITSTATUS判断子进程是否正常退出及其退出状态。

3. 使用SIGCHLD信号处理异步回收

为了避免父进程被阻塞,可以通过信号处理函数异步处理子进程的终止。这在需要父进程继续执行其他任务时非常有用。

例子:使用SIGCHLD处理子进程终止
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <cstring>// 信号处理函数
void sigchld_handler(int signum) {// 循环回收所有已终止的子进程while (true) {int status;pid_t pid = waitpid(-1, &status, WNOHANG);if (pid <= 0) {break;}if (WIFEXITED(status)) {std::cout << "[Signal Handler] 子进程PID:" << pid << " 以状态 " << WEXITSTATUS(status) << " 退出。" << std::endl;}else if (WIFSIGNALED(status)) {std::cout << "[Signal Handler] 子进程PID:" << pid << " 被信号 " << WTERMSIG(status) << " 终止。" << std::endl;}}
}int main() {// 注册SIGCHLD信号处理函数struct sigaction sa;sa.sa_handler = sigchld_handler;sigemptyset(&sa.sa_mask);sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;if (sigaction(SIGCHLD, &sa, NULL) == -1) {std::cerr << "无法注册SIGCHLD处理器:" << strerror(errno) << std::endl;return 1;}pid_t pid = fork();  // 创建子进程if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;}else if (pid == 0) {// 子进程执行的代码std::cout << "子进程PID:" << getpid() << " 启动。" << std::endl;sleep(2);  // 模拟子进程工作std::cout << "子进程PID:" << getpid() << " 结束。" << std::endl;return 24;  // 子进程以状态24退出}else {// 父进程执行的其他任务std::cout << "父进程PID:" << getpid() << " 正在执行其他任务。" << std::endl;// 模拟父进程执行其他任务for (int i = 0; i < 5; ++i) {std::cout << "父进程执行中:" << i + 1 << std::endl;sleep(1);}// 父进程结束前确保所有子进程已被回收// 可以调用wait(NULL)或者让信号处理器完成回收}return 0;
}

输出示例:

父进程PID:12345 正在执行其他任务。
子进程PID:12346 启动。
父进程执行中:1
父进程执行中:2
子进程PID:12346 结束。
[Signal Handler] 子进程PID:12346 以状态 24 退出。
父进程执行中:3
父进程执行中:4
父进程执行中:5

代码解释:

  1. 注册SIGCHLD信号处理器
    • 使用sigaction结构体注册sigchld_handler函数作为SIGCHLD信号的处理器。
    • SA_RESTART标志用于在信号处理后自动重启被中断的系统调用。
    • SA_NOCLDSTOP标志表示当子进程停止或继续时,父进程不接收SIGCHLD信号。
  2. 创建子进程
    • 子进程执行自己的任务并以状态24退出。
  3. 父进程执行其他任务
    • 父进程在等待子进程结束的同时,继续执行其他任务,不会被阻塞。
  4. 信号处理函数sigchld_handler
    • 当子进程终止时,SIGCHLD信号会被触发,sigchld_handler函数会被调用。
    • 在函数内部,使用waitpidWNOHANG选项非阻塞地回收所有已终止的子进程,防止僵尸进程的产生。

4. 避免僵尸进程的策略

  • 及时调用wait()waitpid():确保父进程在子进程终止后,立即回收其资源。
  • 使用信号处理器:如上文所示,通过注册SIGCHLD信号处理器,可以在子进程终止时自动回收资源,而不需要父进程主动等待。
  • 设置SIGCHLDSIG_IGN:在一些系统上,可以通过将SIGCHLD信号的处理方式设置为忽略,从而自动回收子进程资源。这种方法不适用于所有情况,需谨慎使用。
例子:设置SIGCHLD为忽略
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <cstring>int main() {// 设置SIGCHLD为忽略signal(SIGCHLD, SIG_IGN);pid_t pid = fork();  // 创建子进程if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;}else if (pid == 0) {// 子进程执行的代码std::cout << "子进程PID:" << getpid() << " 启动。" << std::endl;sleep(2);  // 模拟子进程工作std::cout << "子进程PID:" << getpid() << " 结束。" << std::endl;return 0;}else {// 父进程执行其他任务std::cout << "父进程PID:" << getpid() << " 正在执行其他任务。" << std::endl;sleep(5);  // 父进程等待子进程结束}return 0;
}

注意事项:

  • 这种方法依赖于系统对SIGCHLD的具体实现,不保证在所有Unix/Linux系统中都有效。
  • 尽管简便,但可能无法获取子进程的退出状态,限制了错误处理和日志记录的能力。

5. 处理多个子进程的终止

当父进程创建多个子进程时,需要确保所有子进程的终止都被正确处理,以避免僵尸进程。可以在SIGCHLD处理函数中使用循环调用waitpid,直到所有终止的子进程都被回收。

例子:处理多个子进程
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <vector>
#include <cstring>// 信号处理函数
void sigchld_handler(int signum) {// 循环回收所有已终止的子进程while (true) {int status;pid_t pid = waitpid(-1, &status, WNOHANG);if (pid <= 0) {break;}if (WIFEXITED(status)) {std::cout << "[Signal Handler] 子进程PID:" << pid << " 以状态 " << WEXITSTATUS(status) << " 退出。" << std::endl;}else if (WIFSIGNALED(status)) {std::cout << "[Signal Handler] 子进程PID:" << pid << " 被信号 " << WTERMSIG(status) << " 终止。" << std::endl;}}
}int main() {// 注册SIGCHLD信号处理函数struct sigaction sa;sa.sa_handler = sigchld_handler;sigemptyset(&sa.sa_mask);sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;if (sigaction(SIGCHLD, &sa, NULL) == -1) {std::cerr << "无法注册SIGCHLD处理器:" << strerror(errno) << std::endl;return 1;}std::vector<pid_t> child_pids;// 创建多个子进程for (int i = 0; i < 3; ++i) {pid_t pid = fork();if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;}else if (pid == 0) {// 子进程执行的代码std::cout << "子进程PID:" << getpid() << " 启动。" << std::endl;sleep(2 + i);  // 模拟不同的工作时间std::cout << "子进程PID:" << getpid() << " 结束。" << std::endl;return i;}else {// 父进程记录子进程PIDchild_pids.push_back(pid);}}// 父进程执行其他任务std::cout << "父进程PID:" << getpid() << " 正在执行其他任务。" << std::endl;sleep(6);  // 等待所有子进程结束// 由于SIGCHLD处理器已经回收了子进程,父进程无需再次调用waitreturn 0;
}

输出:

父进程PID:12345 正在执行其他任务。
子进程PID:12346 启动。
子进程PID:12347 启动。
子进程PID:12348 启动。
子进程PID:12346 结束。
[Signal Handler] 子进程PID:12346 以状态 0 退出。
子进程PID:12347 结束。
[Signal Handler] 子进程PID:12347 以状态 1 退出。
子进程PID:12348 结束。
[Signal Handler] 子进程PID:12348 以状态 2 退出。

代码解释:

  1. 创建多个子进程:循环调用fork()创建三个子进程,每个子进程有不同的工作时间。
  2. 信号处理函数sigchld_handler会被多次调用,以回收每个子进程的资源。
  3. 父进程执行其他任务:父进程在子进程运行期间继续执行其他任务,不会被阻塞。
  4. 无需显式等待:由于信号处理器已经负责回收子进程,父进程无需再次调用wait()waitpid()

6. 使用prctl设置子进程终止时的行为

在某些情况下,可以通过prctl系统调用设置子进程终止时的行为。例如,可以设置PR_SET_CHILD_SUBREAPER,使得特定的进程成为“子进程的收割者”,用于复杂的进程管理。

例子:设置PR_SET_CHILD_SUBREAPER
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <cstring>
#include <sys/prctl.h>int main() {// 将当前进程设置为子进程的收割者if (prctl(PR_SET_CHILD_SUBREAPER, 1) == -1) {std::cerr << "prctl failed: " << strerror(errno) << std::endl;return 1;}pid_t pid = fork();if (pid < 0) {std::cerr << "Fork failed!" << std::endl;return 1;}else if (pid == 0) {// 子进程执行的代码std::cout << "子进程PID:" << getpid() << " 启动。" << std::endl;sleep(2);std::cout << "子进程PID:" << getpid() << " 结束。" << std::endl;return 0;}else {// 父进程作为子进程的收割者,等待子进程结束std::cout << "父进程设置为子进程的收割者,等待子进程结束。" << std::endl;int status;pid_t terminated_pid = wait(&status);if (terminated_pid > 0) {if (WIFEXITED(status)) {std::cout << "子进程PID:" << terminated_pid << " 以状态 " << WEXITSTATUS(status) << " 退出。" << std::endl;}}}return 0;
}

代码解释:

  • prctl(PR_SET_CHILD_SUBREAPER, 1):将当前进程设置为子进程的收割者,使其能够回收其子孙进程的资源。
  • 这种设置在需要复杂的子进程管理,或在容器化环境中非常有用。
http://www.mmbaike.com/news/93836.html

相关文章:

  • 客户关系管理软件有哪些seo优化搜索结果
  • 阿里云域名服务北京seoqq群
  • 网站建设403自己怎么做网站优化
  • 腾讯做网站合肥百度关键词排名
  • 什么网站免费购物商城南宁网站推广营销
  • 免费在线网站模板竞价托管公司排名
  • .net.cn做网站怎么样病毒什么时候才能消失
  • 中国建设工程招聘信息网站怎样推广自己的产品
  • 潍坊行业网站可以免费打开网站的软件下载
  • 如何在百度搜索dw做的网站国内搜索引擎大全
  • 怎么给网站做压力测试商品推广与营销的方式
  • 做网站陪聊下单安徽网站推广公司
  • 做效果图挣钱的网站深圳网络推广外包
  • 论坛类网站可以做移动端吗模板建站和开发网站区别
  • 电子商务网站建设选择服务器要考虑的因素有武汉关键词排名推广
  • 网站SEO容易做吗网络营销的常用工具
  • 青海wap网站建设公司网络营销推广8种方法
  • 网站做外部链接百度小程序优化排名
  • 做哪类视频网站需要视频证书如何注册域名
  • 怎样查网站谁做的谷歌流量代理代理
  • 凡科网站官网登录入口百度品牌广告
  • 做哪些网站比较赚钱可以商用的电视app永久软件
  • 长沙网站制作费用百度引流平台
  • 手机网站特效代码seo关键词优化推广报价表
  • 平面广告设计行业aso关键词排名优化是什么
  • 做网站还赚钱么网站域名解析
  • 济南住房和城乡建设局网站app优化排名
  • 展览设计网站推荐百度关键词搜索优化
  • 如何设计校园网站在线营销推广
  • 宁乡电商网站建设价格百度官网app下载安装