二十七、Linux 进程与信号---进程组和组长进程
27.1 进程组
27.1.1 进程组介绍
- 进程组为一个或多个进程的集合
- 进程组可以接受同一终端的各种信号,同一个信号发送进程组等于发送给组中的所有进程
- 每个进程组有唯一的进程组 ID
- 进程组的消亡要等到组中所有的进程结束
- 进程组的消亡:kill 发送信号给进程组
- kill -9 -进程组号
27.1.2 进程组 ID 获取--- getpgrp 和 getpgid
(1)getpgrp --- 获取调用进程的进程组ID
#include <unistd.h>
pid_t getpgrp(void);
- 函数说明
- getpgrp()用来取得目前进程所属的组识别码。此函数相当于调用 getpgid(0);
- 返回值
- 返回目前进程所属的组识别码。
(2)getpgid --- 获取 pid 所在进程组的 ID
#include <unistd.h>
pid_t getpgid( pid_t pid);
- 函数说明
- getpgid()用来取得参数 pid 指定进程所属的组识别码。如果参数 pid 为0,则会取得目前进程的组识别码。
- 返回值
- 执行成功则返回组识别码,如果有错误则返回 -1 ,错误原因存于 errno 中。
- 错误代码
- ESRCH 找不到符合参数 pid 指定的进程。
- getpgid(getpid()) 获取指定进程的进程组
- getpgid(0) 获取当前进程的进程组
27.2 组长进程
27.2.1 概念
- 每个进程组可以有个组长进程,组长进程的ID就是进程组的ID
- 组长进程可以创建进程组以及该组中的进程
- 进程组的创建从第一个进程(组长进程)加入开始
- 进程组的组号取第一个加入组的进程(组长进程)编号
27.2.2 设置进程组 ID--- setpgid(创建进程组或将指定进程加入到指定的进程组中)
#include <unistd.h>
int setpgid(pid_t pid,pid_t pgid);
- 函数说明
- setpgid() 将参数 pid 指定进程所属的组 ID 设为参数 pgid 指定的组 ID。如果参数 pid 为 0 ,则会用来设置目前进程的组识别码,如果参数 pgid 为0,则会以目前进程的进程 ID 来取代。
- 函数功能:将进程加入到指定的进程组中, pid 为进程号, pgid 为组号
- 返回值
- 执行成功则返回组 ID,如果有错误则返回-1,错误原因存于 errno 中。
- 错误代码
- EINVAL 参数 pgid 小于0。
- EPERM 进程权限不足,无法完成调用。
- ESRCH 找不到符合参数 pid 指定的进程。
27.3 例子
27.3.1 构建进程扇组
构建一个进程扇,要求每两个进程为一个进程组,如下所示
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h> int main(void)
{ //创建进程组,组长进程为父进程
setpgid(getpid(), getpid()); /* 组1 */
// 或 pid_t group1 = getpgid(0);
pid_t group1 = getpgid(getpid());
pid_t group2; int i = ;
pid_t pid; for(; i < ; i++) {
pid = fork();
if(pid < ) {
perror("fork error`");
exit();
} else if(pid > ) {//父进程
//父进程中执行和子进程相同的操作
if(i == ) {
//要注意fork 在父进程中返回的是子进程的 pid
setpgid(pid, group1);
} //第二个子进程作为组长进程,要创建进程组
if(i == ) {
setpgid(pid, pid);
group2 = getpgid(pid);
} if(i == ) {
//第三个子进程加入到 group2
setpgid(pid, group2);
}
} else {//子进程
//将第一个子进程加入到 group1
if(i == ) {
setpgid(getpid(), group1);
} //第二个子进程作为组长进程,要创建进程组
if(i == ){
setpgid(getpid(), getpid());
group2 = getpgid(getpid());
} if(i == ) {
setpgid(getpid(), group2);
} //因为是进程扇,每一个子进程要退出循环
//父进程继续循环 fork
break;
}
} printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid()); //防止僵尸进程产生
for(i = ; i < ; i++) {
wait();
} exit();
}
编译运行:
27.3.2 构建进程链组
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h> int main()
{
//创建进程组1,父进程为组长进程
setpgid(getpid(), getpid());
pid_t group1 = getpgid(getpid()); pid_t pid;
int i = ;
for(;i < ; i++) {
pid = fork();
if(pid < ) {
perror("fork error");
exit();
} else if(pid > ) {
if(i == ) {
//创建进程组2,第一个子进程作为组长进程
setpgid(pid, pid);
} if(i == ) {
//将第二个子进程加入到 group1中
setpgid(pid, group1);
} // 在进程链中,父进程操作完退出循环
break;
} else if(pid == ) { if(i == ) {
//创建进程组2,第一个子进程作为组长进程
setpgid(getpid(), getpid());
} if(i == ) {
//将第二个子进程加入到 group1中
setpgid(getpid(), group1);
}
}
} printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid()); //防止僵尸进程产生
for(i = ; i < ; i++) {
wait();
} return ;
}
编译运行:
27.3.3 进程组删除
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h> int main(void)
{
//创建进程组,父进程作为组长进程
setpgid(getpid(), getpid()); pid_t pid = fork();
if(pid < ){
perror("fork error");
exit();
} else if(pid > ) {
//将子进程加入到父进程所在的组
setpgid(pid, getpgid(getpid()));
} else {
//将子进程加入到父进程所在的组
setpgid(getpid(), getpgid(getppid()));
} printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid()); pause();//进程暂停,等待信号 return ;
}
编译运行:
(1)杀掉进程组
(2)杀掉父进程
杀掉父进程后,子进程依然存在,只不过变成了孤儿进程,并被2323进程所领养
(3)杀掉子进程
子进程变为了僵尸进程,子进程被杀死,但是父进程并没有回收子进程。
杀掉父进程:
僵尸进程被回收
27.3.4 子进程不加入父进程组中
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h> int main(void)
{
//创建进程组,父进程作为组长进程
setpgid(getpid(), getpid()); pid_t pid = fork();
if(pid < ){
perror("fork error");
exit();
} else if(pid > ) {
//将子进程加入到父进程所在的组
setpgid(pid, getpgid(getpid()));
} else {
//将子进程加入到父进程所在的组
//setpgid(getpid(), getpgid(getppid()));
} printf("pid: %d, ppid: %d, pgid: %d\n", getpid(), getppid(), getpgid()); pause();//进程暂停,等待信号 return ;
}
编译运行:
没有将子进程加入到组中,依然将子进程加入到父进程组了。
注意:从 shell 上启动一个父进程,然后从父进程上创建若干个子进程,默认情况下都加入到父进程所在的组中,组号就是父进程的 PID,组长就为父进程。
二十七、Linux 进程与信号---进程组和组长进程的更多相关文章
- 二十八、Linux 进程与信号---前台进程组
28.1 介绍 28.1.1 概念 自动接受终端信号的组称为前台进程组 在终端通过 ctrl + c 等动作产生的信号首先被前台进程组接受 在 shell 启动的若干个进程组默认是父进程所在的组为前台 ...
- (二十七)Linux的inode的理解
一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统 ...
- linux 下信号处理命令trap && linux下各种信号的意义
1.用途说明 trap是一个shell内建命令,它用来在脚本中指定信号如何处理.比如,按Ctrl+C会使脚本终止执行,实际上系统发送了SIGINT信号给脚本进程,SIGINT信号的默认处理方式就是退出 ...
- 第9章 Linux进程和信号超详细分析
9.1 进程简单说明 进程是一个非常复杂的概念,涉及的内容也非常非常多.在这一小节所列出内容,已经是我极度简化后的内容了,应该尽可能都理解下来,我觉得这些理论比如何使用命令来查看状态更重要,而且不明白 ...
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...
- 三十一、Linux 进程与信号——SIGCHLD 信号、kill和raise函数以及alarm函数
31.1 SIGCHLD 信号 子进程状态发生变化(子进程结束)产生该信号,父进程需要使用 wait 调用来等待子进程结束并回收它. 避免僵尸进程 #include <stdio.h> # ...
- Linux/UNIX之信号(1)
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/walkerkalr/article/details/24462723 信号(1) 信号是软件中断.每 ...
- 25 Linux中的信号
Linux中的信号 信号是进程在运行过程中,由自身产生或由进程外部发过来的消息(事件).每个信号用一个整型常量宏表示,以SIG开头,比如SIGCHLD.SIGINT等,它们在系统头文件中定义,也可以通 ...
- Linux 两组信号对比(关闭和停止进程信号)
之前看信号的时候,没有太注意不同信号的对比.今天再次看到的时候,突然感觉对一些信号,非常相似,乃至非常容易混淆.今天周末就抽空总结一下. 一.关闭进程信号 常见的4中关闭进程信号是SIGKILL,SI ...
随机推荐
- centos7破解安装confluence5.9.11
应用环境:Confluence是一个专业的企业知识管理与协同软件,也可以用于构建企业wiki.通过它可以实现团队成员之间的协作和知识共享. 安装环境:centos7.3 Java环境 1.7.0_79 ...
- #1014 : Trie树 HihoCoder(字典树)
描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题: ...
- HDU--4825 Xor Sum (字典树)
题目链接:HDU--4825 Xor Sum mmp sb字典树因为数组开的不够大一直wa 不是报的 re!!! 找了一下午bug 草 把每个数转化成二进制存字典树里面 然后尽量取与x这个位置上不相同 ...
- Ubuntu下搜狗输入法无法输入中文
现象:无法打出中文,但是有输入框.如下图所示情形: 解决方法 删除配置文件,重启fcitx 配置文件在~/.config下的3个文件夹里SogouPY.SogouPY.users.sogou-qimp ...
- 【洛谷P2585】三色二叉树
题目大意:给定一个二叉树,可以染红绿黄三种颜色,要求父节点和子节点的颜色不同,且如果一个节点有两个子节点,那么两个子节点之间的颜色也不同.求最多和最少有多少个节点会被染成绿色. 题解:加深了对二叉树的 ...
- request 的介绍使用属性
上下文:相当于一个容器,保存了 Flask 程序运行过程中的一些信息. Flask中有两种上下文,请求上下文和应用上下文 请求上下文(request context) 在 flask 中,可以直接在视 ...
- script id
Script中的id还是有用的,比如如果页面需要加载的JS文件过多,那样最好是写一个JS文件用来加载这些JS文件 require: function(libraryName){ document.wr ...
- PMP项目管理考试培训机构内部资料打包赠送(3个PPT)
PMP认证考试我自己这边是今年6月份考过了的,手里觉得对自己有帮助的资料就是这3个PPT,讲解的比较清晰,知识点详细.结合自己做的笔记,备考十分轻松.所以推荐大家也看一下. 有需要的可以联系. PPT ...
- linux系统调用之系统控制
ioctl I/O总控制函数 _sysctl 读/写系统参数 acct 启用或禁止进程记账 getrlimit 获取系统资源上限 setrlimit 设置系统资源上限 getrusage 获取系统资源 ...
- 导出为word文档
原来用freemarker就可以,真是太简便了.先设计一张文档,然后把要输出的值用freemarker取值表达式获取数据,最后保存为ftl文件,再调整一下就可以了.