进程组和用处
进程组:一个或多个进程的集合,进程组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树的…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用
Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用 Linux 内核内存管理是构成整个内核性能和系统稳定性的基础,但这一子系统结构复杂,常常有设置失败、性能展示不良、OOM 杀进程等问题。要分析这些问题,需要一套工具化、…...
持续交付的进化:从DevOps到AI驱动的IT新动能
文章目录 一、持续交付的本质:从手动到自动的交付飞跃关键特性案例:电商平台的高效部署 二、持续交付的演进:从CI到AI驱动的未来发展历程 中国…...
Linux知识回顾总结----进程状态
本章将会介绍进程的一些概念:冯诺伊曼体系结构、进程是什么,怎么用、怎么表现得、进程空间地址、物理地址、虚拟地址、为什么存在进程空间地址、如何感性得去理解进程空间地址、环境变量是如何使用的。 目录 1. 冯诺伊曼体系结构 1.1 是什么 1.2 结论 …...
Three.js + Vue3 加载GLB模型项目代码详解
本说明结合 src/App.vue 代码,详细解释如何在 Vue3 项目中用 three.js 加载并显示 glb 模型。 1. 依赖与插件导入 import {onMounted, onUnmounted } from vue import * as THREE from three import Stats from stats.js import {OrbitControls } from three/examples/jsm/co…...
PHP文件读取漏洞全面剖析:触发点与利用技术
PHP文件读取漏洞全面剖析:触发点与利用技术 引言 PHP作为Web开发中最流行的语言之一,其文件操作功能强大但也暗藏风险。文件读取漏洞是PHP应用中最常见的安全问题之一,攻击者利用这些漏洞可以读取服务器敏感文件,甚至实现远程代…...
低空城市场景下的多无人机任务规划与动态协调!CoordField:无人机任务分配的智能协调场
作者:Tengchao Zhang 1 ^{1} 1 , Yonglin Tian 2 ^{2} 2 , Fei Lin 1 ^{1} 1, Jun Huang 1 ^{1} 1, Patrik P. Sli 3 ^{3} 3, Rui Qin 2 , 4 ^{2,4} 2,4, and Fei-Yue Wang 5 , 1 ^{5,1} 5,1单位: 1 ^{1} 1澳门科技大学创新工程学院工程科学系࿰…...
