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

Linux进程通信:进程组 会话

1. 进程组

(1)概念:一个或多个进程的集合,也称为“作业”。

(2)父进程创建子进程时,默认属于同一个进程组。进程组ID为组长进程ID。

(3)进程组中只要有一个进程存在,进程组就存在,与组长进程是否终止无关。

(4)父子进程可不属于同一进程组。


进程组相关函数

(1)getpgrp函数

#include<unistd.h>pid_t getpgrp(void);
/*
功能:获取当前进程的进程组ID
返回值:总是成功。
*/

(2)getpgid函数

#include<unistd.h>pid_t getpgid(pid_t pid);
/*
功能:获取指定进程的进程组ID
参数:pid:进程号;若为0,则功能和getpgrp一样
返回值:成功:进程组ID失败:-1
*/

(3)setpgid函数

#include<unistd.h>int setpgid(pid_t pid, pid_t pgid);
/*
功能:将进程pid的进程组改为pgid;可创建新的进程组
返回值:成功:0失败:-1
*/

2. 会话

概念:一个或多个进程组的集合。

创建会话注意事项:

(1)组长进程不能创建会话,否则返回出错;

(2)创建会话的非组长进程变成新会话的首进程(session header,也称为会长进程),同时会创建一个新进程组并成为组长进程(因为新会话中至少要有一个进程组);

(3)组长进程不会成为新会话首进程,新会话首进程会成为组长进程;

(4)需要root权限(Ubuntu等除外);

(5)新会话丢弃原有控制终端,该会话无控制终端;

(6)创建新会话时:先调用fork,父进程终止,子进程调用setsid(创建会话函数);

会话相关函数:

(1)getsid函数:

#include<unistd.h>pid_t getsid(pid_t pid);
/*
功能:获取进程所属的会话
参数:pid:进程号;若为0则表示查看当前进程的会话ID
返回值:成功:会话ID失败:-1
*/

getsid示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>int main(int argc, const char* argv[]) {pid_t pid = -1;// 获取当前进程组会话IDpid = getsid(0);if (-1 == pid) {perror("getsid");return 1;}printf("当前进程的会话ID:%d\n", pid);return 0;
}

运行结果:

(2)setsid函数

#include<unistd.h>pid_t setsid(void);
/*
功能:创建新会话,并用自己的ID设置为新进程组ID和新会话ID;该进程将成为新进程组组成和新会话会长。
返回值:成功:新会话ID;失败:-1.
*/

setsid示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>int main(int argc, const char* argv[]) {pid_t pid = -1;printf("父进程pid:%d\n", getpid());printf("父进程所属进程组的组长进程pid:%d\n", getpgrp());printf("父进程所属会话的会长进程pid:%d\n", getsid(0));// 创建新会话printf("父进程%d即将创建新会话...\n", getpid());pid = setsid(); // 失败if (-1 == pid) {printf("创建失败!父进程为组长进程,组长进程不可创建新会话..\n");perror("setsid");}pid = fork();if (-1 == pid) {perror("fork");return 1;}if (0 == pid) {  // 子进程printf("\n子进程创建成功!其pid:%d,其组长进程:%d\n", getpid(), getpgrp());printf("子进程%d即将创建新会话...\n", getpid());pid = setsid(); // 创建会话if (-1 == pid) {perror("setsid");return 1;}printf("子进程创建新会话成功\n");printf("子进程所属进程组的组长进程pid:%d\n", getpgrp());printf("子进程所属会话的会长进程pid:%d\n", getsid(0));printf("子进程的父进程pid:%d\n", getppid());} else {sleep(2);printf("\n子进程创建会话后,父进程情况:\n");printf("父进程所属进程组的组长进程pid:%d\n", getpgrp());printf("父进程所属会话的会长进程pid:%d\n", getsid(0));while (1) {sleep(1);}}return 0;
}

运行结果:

结果可知:

(1)组长进程不可创建新会话;

(2)非组长进程(这个示例中的子进程)创建新会话后会成为新会话的会长,同时也会创建一个新进程组并成为组长(因为新会话中至少要有一个进程组)

(3)子进程创建新会话成为新会长和新组长后,并不会影响父进程的组长和会长;

(4)父子进程可不属于同一个进程组,也可不属于同一会话。

http://www.lryc.cn/news/64114.html

相关文章:

  • 【前端面经】JS-深浅拷贝
  • 【自然语言处理】实验2布置:Word2Vec TransE案例
  • Redis集合底层实现原理
  • OVS常用命令与使用总结
  • 一以贯之:从城市网络到“城市一张网”
  • 【Java校招面试】基础知识(四)——JVM
  • 项目管理-计算专题(三点估算、PERT估算)
  • 【华为OD机试 2023最新 】模拟商场优惠打折(C语言题解 100%)
  • 使用TrieTree(字典树)来实现敏感词过滤
  • USB转串口芯片CH9101U
  • Java语言介绍
  • 终于把 vue-router 运行原理讲明白了(二)!!!
  • ChatGPT实现服务器体验沙箱
  • 【算法】刷题中的位运算
  • 9.Java中异常处理机制是什么
  • GeoTools实战指南: 叠加GeoTIFF与Shapefile图层生成截图
  • nginx配置sh脚本远程执行一键安装
  • Excel表格成绩排名全攻略,让你事半功倍!
  • Docker 持久化存储 Bind mounts
  • LVS +Keepalived 高可用群集部署
  • Kafka调优
  • Debezium系列之:详细介绍Debezium2.X版本导出Sqlserver数据库Debezium JMX指标的方法
  • 基于PWM技术的三相光伏逆变器研究(Simulink)
  • 〖Python网络爬虫实战㉑〗- 数据存储之JSON操作
  • 不得不说的行为型模式-责任链模式
  • 基于dsp+fpga+AD+ENDAC的半导体运动台高速数据采集电路仿真设计(四)
  • 快速搭建Electron+Vite3+Vue3+TypeScript5脚手架 (无需梯子,快速安装Electron)
  • 语义分割学习笔记(二)转置卷积
  • docker运行PostgreSQL数据库维护,执行脚本备份数据库与更新表结构
  • 【计算机网络】127.0.0.1、0.0.0.0、localhost地址是什么?