进程组和用处
进程组:一个或多个进程的集合,进程组id是一个正整数。
组长进程:进程组id == 进程id
组长进程可以创建一个进程组,创建该进程组的进程,终止了,只要进程组有一个进程存在,进程组就存在,与组长进程是否终止无关。
进程组生存期:进程组创建到最后一个进程离开(终止或转移到另一个进程组)
一个进程可以为自己或子进程设置进程组id
作用:
子进程退出时,不管父子进程同不同一个进程组,都会发SIGCHLD信号给父进程
当父子进程同进程组时,父进程应捕捉SIGCHLD信号,对子进程资源进程回收,防止僵尸进程的产生
当父子进程不同进程组时,比如设置子进程成为了一个新的进程组,这时候子进程退出,系统也会正常回收子进程的资源,不会产生僵尸进程的
相关函数
#include <unistd.h>
int setpgid(pid_t pid, pid_t pgid); //pid = 0, pgid = 0,让当前进程成为一个进程组,并且进程组id为当前进程的pid
pid_t getpgid(pid_t pid); //pid = 0,获取当前进程的进程组id
pid_t getpgrp(void); /* POSIX.1 version */
pid_t getpgrp(pid_t pid); /* BSD version */
int setpgrp(void); /* System V version */
int setpgrp(pid_t pid, pid_t pgid); /* BSD version */
demo
父子进程同一个进程组
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>void do_sigchld(int signo)
{pid_t pid;int status;printf("signo = %d\n", signo);while((pid = waitpid(0, &status, WNOHANG)) > 0) // 0:跟调用进程同组的子进程,WNOHANG:不阻塞,立即返回{if (WIFEXITED(status))printf("child %d exit status %d\n", pid, WEXITSTATUS(status));else if (WIFSIGNALED(status))printf("chid %d exit by signal %d\n", pid, WTERMSIG(status));}
}int main(int argc, char *argv[])
{pid_t pid;//阻塞SIGCHLD信号sigset_t set;sigemptyset(&set);sigaddset(&set, SIGCHLD);sigprocmask(SIG_BLOCK, &set, NULL);pid = fork();if (pid == 0){//in child//解除阻塞SIGCHLD信号sigprocmask(SIG_UNBLOCK, &set, NULL);//进程组printf("child pid = %d, process group id getpgid(0) = %d\n", getpid(), getpgid(0));printf("child pid = %d, process group id getpgid(getpid()) = %d\n", getpid(), getpgid(getpid()));printf("child pid = %d, process group id getpgrp() = %d\n", getpid(), getpgrp());/*setpgid(0, 0); //pid = 0, pgid = 0,让当前进程成为一个进程组,并且进程组id为当前进程的pidprintf("after setpgid(0, 0) child pid = %d, process group id getpgid(0) = %d\n", getpid(), getpgid(0));printf("after setpgid(0, 0) child pid = %d, process group id getpgid(getpid()) = %d\n", getpid(), getpgid(getpid()));printf("after setpgid(0, 0) child pid = %d, process group id getpgrp() = %d\n", getpid(), getpgrp());*/}else if (pid > 0){//in parent//先捕捉SIGCHLD信号struct sigaction act;act.sa_handler = do_sigchld;sigemptyset(&act.sa_mask);act.sa_flags = 0; //0:用sa_handler参数,SA_SIGINFO:用sa_sigaction参数sigaction(SIGCHLD, &act, NULL);//再解除阻塞SIGCHLD信号sigprocmask(SIG_UNBLOCK, &set, NULL);//进程组printf("parent pid = %d, process group id getpgid(0) = %d\n", getpid(), getpgid(0));printf("parent pid = %d, process group id getpgid(getpid()) = %d\n", getpid(), getpgid(getpid()));printf("parent pid = %d, process group id getpgrp() = %d\n", getpid(), getpgrp());sleep(1); //为了观察子进程退出时,父进程回收子进程资源}else{perror("fork");exit(1);}return 0;
}
子进程成为一个进程组时,上面的代码加入如下代码后
setpgid(0, 0); //pid = 0, pgid = 0,让当前进程成为一个进程组,并且进程组id为当前进程的pid
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>void do_sigchld(int signo)
{pid_t pid;int status;printf("signo = %d\n", signo);while((pid = waitpid(0, &status, WNOHANG)) > 0) // 0:跟调用进程同组的子进程,WNOHANG:不阻塞,立即返回{if (WIFEXITED(status))printf("child %d exit status %d\n", pid, WEXITSTATUS(status));else if (WIFSIGNALED(status))printf("chid %d exit by signal %d\n", pid, WTERMSIG(status));}
}int main(int argc, char *argv[])
{pid_t pid;//阻塞SIGCHLD信号sigset_t set;sigemptyset(&set);sigaddset(&set, SIGCHLD);sigprocmask(SIG_BLOCK, &set, NULL);pid = fork();if (pid == 0){//in child//解除阻塞SIGCHLD信号sigprocmask(SIG_UNBLOCK, &set, NULL);//进程组printf("child pid = %d, process group id getpgid(0) = %d\n", getpid(), getpgid(0));printf("child pid = %d, process group id getpgid(getpid()) = %d\n", getpid(), getpgid(getpid()));printf("child pid = %d, process group id getpgrp() = %d\n", getpid(), getpgrp());setpgid(0, 0); //pid = 0, pgid = 0,让当前进程成为一个进程组,并且进程组id为当前进程的pidprintf("after setpgid(0, 0) child pid = %d, process group id getpgid(0) = %d\n", getpid(), getpgid(0));printf("after setpgid(0, 0) child pid = %d, process group id getpgid(getpid()) = %d\n", getpid(), getpgid(getpid()));printf("after setpgid(0, 0) child pid = %d, process group id getpgrp() = %d\n", getpid(), getpgrp());}else if (pid > 0){//in parent//先捕捉SIGCHLD信号struct sigaction act;act.sa_handler = do_sigchld;sigemptyset(&act.sa_mask);act.sa_flags = 0; //0:用sa_handler参数,SA_SIGINFO:用sa_sigaction参数sigaction(SIGCHLD, &act, NULL);//再解除阻塞SIGCHLD信号sigprocmask(SIG_UNBLOCK, &set, NULL);//进程组printf("parent pid = %d, process group id getpgid(0) = %d\n", getpid(), getpgid(0));printf("parent pid = %d, process group id getpgid(getpid()) = %d\n", getpid(), getpgid(getpid()));printf("parent pid = %d, process group id getpgrp() = %d\n", getpid(), getpgrp());sleep(1); //为了观察子进程退出时,父进程回收子进程资源}else{perror("fork");exit(1);}return 0;
}
相关文章:
进程组和用处
进程组:一个或多个进程的集合,进程组id是一个正整数。组长进程:进程组id 进程id组长进程可以创建一个进程组,创建该进程组的进程,终止了,只要进程组有一个进程存在,进程组就存在,与…...
Nacos集群+Nginx负载均衡
搭建Nacos集群 注意: 3个或3个以上Nacos节点才能构成集群。要求服务器内存分配最好大于6G以上(如果不够则需修改nacos启动脚本中的默认内存配置)根据nacos自带的mysql建库脚本建立对应数据库(/conf/nacos-mysql.sql)如果是三台服…...
TypeScript 学习之类型兼容
TypeScript 的类型兼容性是基于结构子类型的。 结构类型是一种只使用其成员来描述类型的方式。 interface Named {name: string; }class Person {name: string; }let p: Named; p new Person();// 赋值成功,因为都是结构类型,只要Person 类型的包含 Nam…...
Linux软件管理RPM
目录 前言 RPM软件管理程序:rpm RPM默认安装的路径 PRM讲解前准备工作 RPM安装(install) RPM查询(query) RPM卸载(erase) RPM升级与更新(upgrade/freshen) RPM重…...
01背包问题
背包问题的递归解决过程如下: 第一步明确思路 在解决问题之前,为描述方便,首先定义一些变量:Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积,定义V(i,j):当前背包容量 j,前 i 个…...
14_FreeRTOS二值信号量
目录 信号量的简介 队列与信号量的对比 二值信号量 二值信号量相关API函数 实验源码 信号量的简介 信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问。 假设有一个人需要在停车场停车 1.首先判断停车场是否还有空车位(判断信号量是否有资源) 2.停车场正好…...
JavaScript随手笔记---轮播图(点击切换)
💌 所属专栏:【JavaScript随手笔记】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &#…...
机器人学 markdown数学公式常用语法
参考链接1 本文包含了markdown常用的数学公式,按照目录可查询选用 初始类 行内数学公式均用两个符号包裹行间数学公式均用两个符号包裹 行间数学公式均用两个符号包裹行间数学公式均用两个符号包裹,用于表示重要的、需在行间单独列出的公式 $行内数学…...
如何使用 Python 语言来编码和解码 JSON 对象
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写。 JSON 函数 使用 JSON 函数需要导入 json 库:import json。 函数 描述 json.dumps 将 Python 对象编码成 JSON 字符串 json.loads 将已编码的 JSON 字符串解码为 Pyth…...
【蓝桥云课】求正整数的约数个数
一、求正整数n的约数个数 方法一(常用算法):从1到n逐一判断其能否整除n,若能整除n即为n的约数,否则不是n的约数。 方法二:从1到n\sqrt{n}n逐一判断是否为n的约数,当n\sqrt{n}n为n的约数时,个数加1&…...
刷题记录: wannafly25 E 牛客NC19469 01串 [线段树维护动态dp]
传送门:牛客 题目描述: Bieber拥有一个长度为n的01 串,他每次会选出这个串的一个子串作为曲谱唱歌,考虑该子串从左 往右读所组成的二进制数P。 Bieber每一秒歌唱可以让P增加或减少 2 的 k次方(k由Bieber选 定),但必须…...
懂九转大肠的微软New Bing 内测申请教程
最近微软的New Bing开放内测了,网上已经有拿到内测资格的大佬们对比了ChatGPT和New Bing。对比结果是New Bing比ChatGPT更强大。来看看具体对比例子吧 1.时效性更强 ChatGPT的库比较老,跟不上时事,比如你问它九转大肠的梗,ChatG…...
WRAN翻译
基于小波的图像超分辨残差注意力网络 Wavelet-based residual attention network for image super-resolution 代码: https://github.com/xueshengke/WRANSR-keras 摘要: 图像超分辨率技术是图像处理和计算机视觉领域的一项基础技术。近年来,…...
ROS学习笔记——第二章 ROS通信机制
主要跟着[1]学习ros::Rate r(1); //错误,应改为ros::Rate r(10);[2]对Topic通信打的比方很形象,便于理解记忆。[3]有整个过程的图片,对于初学者更加友好[4]对发布者的代码注释非常好,方便进一步学习此外CMake官方文档可以查询相关…...
MacOS Pytorch 机器学习环境搭建
学习 Pytorch ,首先要搭建好环境,这里将采用 Anoconda Pytorch PyCharm 来一起构建 Pytorch 学习环境。 1. Anoconda 安装与环境创建 Anoconda 官方介绍:提供了在一台机器上执行 Python/R 数据科学和机器学习的最简单方法。 为什么最简单…...
项目——博客系统
文章目录项目优点项目创建创建相应的目录,文件,表,导入前端资源实现common工具类实现拦截器验证用户登录实现统一数据返回格式实现加盐加密类实现encrypt方法实现decrypt方法实现SessionUtil类实现注册页面实现前端代码实现后端代码实现登录页…...
PHP(14)会话技术
PHP(14)会话技术一、概念二、分类三、cookie技术1. cookie的基本使用2. cookie的生命周期3. cookie的作用范围4. cookie的跨子域5. cookie的数组数据四、session1. session原理2. session基本使用3. session配置4. 销毁session一、概念 HTTP协议是一种无…...
对JAVA 中“指针“理解
对于Java中的指针,以下典型案例会让你对指针的理解更加深刻。 首先对于: 系统自动分配对应空间储存数字 1,这个空间被变量名称b所指向即: b ——> 1 变量名称 空间 明…...
功率放大器在MEMS微结构模态测试研究中的应用
实验名称:功率放大器在MEMS微结构模态测试研究中的应用研究方向:元器件测试测试目的:随着MEMS器件在各个领域中广泛应用,对微结构进行模态测试获得其动态特性参数对微结构的设计、仿真、制造、以及质量控制和评价等方面具有十分重…...
【算法基础】字典树(Trie树)
一、Trie树原理介绍 1. 基本概念 Trie 树,也叫“字典树”。顾名思义,它是一个树形结构。它是一种专门处理字符串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串的问题。【高效存储和查找字符串集合的数据结构】,存储形式如下: 2. 用数组来模拟Trie树的…...
终极指南:如何快速配置HsMod插件提升炉石传说游戏体验
终极指南:如何快速配置HsMod插件提升炉石传说游戏体验 【免费下载链接】HsMod Hearthstone Modify Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod HsMod是一个基于BepInEx框架开发的炉石传说游戏插件,专为希望提升游…...
Qwen3.5-4B模型网络协议分析应用:模拟客户端与解析通信数据
Qwen3.5-4B模型网络协议分析应用:模拟客户端与解析通信数据 1. 网络协议分析的AI新思路 网络协议分析一直是运维工程师和安全研究人员的日常工作重点。传统方法需要人工查阅RFC文档、编写测试代码、分析抓包数据,整个过程耗时费力。Qwen3.5-4B模型的出…...
Claude Code架构深度解析:从核心文件到Harness的确定性控制体系
前言 Claude Code凭借强大的代码理解、编辑与执行能力,成为AI研发工程师的高效工具,但多数使用者仅停留在功能调用层面,对其底层架构尤其是核心控制层Harness知之甚少。作为Claude Code架构师,本文将从项目架构视角,拆…...
智能仓储环境监控避坑指南:51单片机系统常见问题与解决方案
智能仓储环境监控避坑指南:51单片机系统常见问题与解决方案 在工业4.0时代,智能仓储系统的稳定运行直接关系到企业供应链效率。作为核心控制单元,51单片机以其高性价比和成熟生态,在中小型仓储环境监控中占据重要地位。然而实际部…...
 轻松构建可信的智能代理:AgentScope框架介绍
什么是 AgentScope? AgentScope 是一个生产就绪的、易于使用的代理框架,它提供了与不断增强的模型能力相兼容的基本抽象,并且内置支持微调功能。我们为越来越具代理性的语言模型(LLMs)设计这种框架,方法是…...
OpenClaw多模型对比:Qwen3.5-4B-Claude与基础版任务实测
OpenClaw多模型对比:Qwen3.5-4B-Claude与基础版任务实测 1. 测试背景与模型选择 最近在搭建个人自动化工作流时,我发现OpenClaw的任务执行质量高度依赖底层大模型的推理能力。为了找到最适合复杂任务的模型,我决定对两个版本进行系统测试&a…...
生产环境的 AOP:性能损耗分析与异常处理最佳实践
在开发环境,AOP 是我们的神兵利器,日志、事务、权限一把梭。 但在生产环境,AOP 往往是一把双刃剑: 用好了,它是系统的“黑匣子”和“安全网”; 用不好,它就是性能杀手和故障黑洞。很多开发者最怕…...
抖音批量下载工具:高效自动化内容采集解决方案
抖音批量下载工具:高效自动化内容采集解决方案 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 在内容创作与数据分析领域,高效获取抖音视频资源是许多从业者面临的共同挑战。传统手动…...
让ai安装ai:使用快马平台智能分析环境并自动生成最优dify部署与调优方案
最近在折腾Dify的安装部署,发现这个AI驱动的开发平台本身也需要AI来辅助安装,真是个有趣的循环。好在发现了InsCode(快马)平台,用它的AI能力帮我解决了这个"用AI装AI"的需求。记录下这个智能化安装方案的设计思路,或许能…...
OpenClaw私有化部署指南:Qwen3-VL:30B+飞书智能助手
OpenClaw私有化部署指南:Qwen3-VL:30B飞书智能助手 1. 为什么选择本地化部署? 去年我接手了一个需要处理大量敏感数据的项目,团队最初尝试使用公有云API,但很快遇到了数据合规问题。这促使我开始研究本地化AI解决方案࿰…...
