---- 整理自狄泰软件唐佐林老师课程
查看所有文章链接:(更新中)Linux系统编程训练营 - 目录
文章目录
- 1. 详解Linux进程组
- 1.1 Linux进程组
- 1.2 进程组示例程序
- 1.3 编程实验:Linux进程组
- 1.4 深入理解进程组
- 1.4.1 进程组标识设置技巧
- 1.4.2 编程实验一
- 1.4.3 编程实验二
- 2. 会话与终端的关系
- 2.1 Linux会话(session)
- 2.2 会话与终端
- 2.3 登录实验
- 2.4 会话与前后台进程组
- 2.4.1 问题
- 2.4.2 实验
- 3. 会话编程深度剖析
- 3.1 Linux会话接口
- 3.2 实例
1. 详解Linux进程组
1.1 Linux进程组
- 每个进程都有一个 进程组号(PGID)
- 进程组:一个或多个进程的集合(集合中的进程并不孤立)
- 进程组中的进程通常存在 父子关系,兄弟关系,或功能相近
- 进程组可方便进程管理(如:同时杀死多个进程,发送一个信号给多个进程)
- 每个进程必定属于一个进程组,也只能属于一个进程组
- 进程除了有PID外,还有PGID(唯一,但可变)
- 每个进程组有一个 进程组长,进程组长的PID和PGID相同
pid_t getpgrp(void); // 获取当前进程的组标识
pid_t getpgid(pid_t pid); // 获取指定进程的组标识
- 对于
int setpgid(pid_t pid, pid_t pgid); // 设置pid进程的进程组标识为pgid
:- 如果pid == pgid,将pid指定的进程设为组长
- 如果pid == 0,设置当前进程的组标识为pgid
- 如果pgid == 0,则将pid作为组标识
注释:
- 函数作用:setpgid(pid, pgid) 将pid进程的进程组ID设置成pgid,创建一个新进程组或加入一个已存在的进程组
- 函数性质:
- 性质1:一个进程只能为 自己或子进程 设置进程组ID,不能设置其父进程的进程组ID。
- 性质2:if(pid == pgid),由pid指定的进程变成进程组长;即进程pid的进程组标识pgid为pid。
- 性质3:if(pid==0),将当前进程的pid作为进程组ID。
- 性质4:if(pgid==0),将pid作为进程组ID。
- 默认情况下,子进程与父进程 属于 同一个进程组
1.2 进程组示例程序
1.3 编程实验:Linux进程组
【参看链接】:09 - Linux进程层次分析 / 00进程组 / pgid_j.c
1.4 深入理解进程组
- 进程组长终止,进程组依然存在(进程组长仅用于创建新进程组),进程组中的 所有进程 结束之后,进程组消亡
- 父进程创建子进程后立即通过 setpgid() 改变子进程的组标识(PGID),子进程从父进程的进程组移动到组标识的进程组;同时,子进程也需要通过 setpgid() 改变自身组标识(PGID)
- 子进程 如果调用exec(),那么:
- 父进程无法通过setpgid()改变子进程的组标识(PGID)
- 子进程只能自身通过setpgid()改变组标识(PGID)
1.4.1 进程组标识设置技巧
1.4.2 编程实验一
【参看链接】:09 - Linux进程层次分析 / 01进程组标识设置技巧 / pgid_a.c
1.4.3 编程实验二
【参看链接】:09 - Linux进程层次分析 / 02进程组中用execve
- 未加延时
- 加延时
注释:代码中的sleep(1),使得子进程先调用了evec(),父进程无法再通过setpgid()改变子进程的组标识(PGID)。
2. 会话与终端的关系
2.1 Linux会话(session)
- 用户通过终端登陆系统后会产生一个 会话
- 会话是 一个或多个 进程组 的集合
- 每个会话有一个 会话标识(SID)
- 终端登录后的第一个进程成为 会话首进程,通常是一个 shell / bash
- 对于会话首进程(session leader),其PID和SID相等,SID == PID
会话 SID | ||||||
---|---|---|---|---|---|---|
进程组 PGID | 进程组 PGID | ... | ||||
进程 PID | 进程 PID | ... | 进程 PID | 进程 PID | ... | ... |
2.2 会话与终端
- 通常情况下,会话 与一个 终端(控制终端) 相关联 用于执行输入输出操作
- 会话首进程 建立与 控制终端 的连接(会话首进程又叫 控制终端)
- 会话中的进程组可分为:
- 前台进程组:可接收控制终端中的输入,也可输出数据到控制终端
- 后台进程组:所有进程后台运行,无法接受终端中的输入,但可输出数据到终端
- 每个会话最多只有一个前台进程组,可以有多个后台进程组
2.3 登录实验
- 准备
注释:
agetty 是一个在 Linux 系统上使用的程序,用于提供控制台终端的登录功能。它是 “getty”(“适配器调制解调器”的缩写)的一个变体,是一种用于处理终端登录的程序。
agetty 的中文解释可以是 “虚拟终端登录程序” 或者 “控制台终端登录程序”。它通常用于在 Linux 系统上配置和管理虚拟终端(也称为控制台终端)的登录过程。
agetty 在启动时会监视一个或多个虚拟终端设备,并等待用户输入用户名和密码。一旦用户成功登录,agetty 将为其提供一个交互式的命令行界面,以便用户可以执行各种命令和操作。
agetty 提供了一些配置选项,可以控制登录界面的外观和行为,例如登录提示符、超时设置和登录失败处理等。这使得系统管理员能够根据特定的需求和安全策略来自定义登录过程。
总之,agetty 是一个用于管理控制台终端登录的程序,在 Linux 系统上广泛使用。
- 此时,在虚拟机Ubuntu下同时按住 ctrl+alt+F6 进入6号终端,这时候先不进行登录:
- 同时按住 ctrl+alt+F2 回到shell图形界面:
- 切换到6号终端,只输入用户名,不登录:
- 切换回图形界面:
- 切换到6号终端,输入密码登录:
- 切换回图形界面:
2.4 会话与前后台进程组
2.4.1 问题
- 问题1:
- 在终端中输入命令后,会发生什么?
- 当命令行shell 运行命令后创建一个新的进程组
- 如果运行的命令中有 多个子命令 则创建 多个进程(处于新建的进程组中)
- 命令 不带 &
shell将新建的进程组设置为 前台进程组,并将自己暂时设置为后台进程组 - 命令 带 &
shell将新建的进程组设置为 后台进程组,自己依旧是前台进程组
- 在终端中输入命令后,会发生什么?
- 问题2:
- 什么是 终端进程组标识(TPGID)?
- 标识进程 是否 处于一个 和终端相关 的进程组中
- 前台进程组:TPGID == PGID
- 后台进程组:TPGID != PGID
- 若进程和任何终端无关:TPGID == -1
- 什么是 终端进程组标识(TPGID)?
- 通过比较TPGID与PGID可判断:一个进程是属于前台进程组,还是后台进程组。
由于前台进程组可能改变,TPGID用于标识当前的前台进程组
2.4.2 实验
【参看链接】:09 - Linux进程层次分析 / 03TPGID / pgid_j.c
- 不带 &
- 带 &
3. 会话编程深度剖析
3.1 Linux会话接口
#include <unistd.h>
pid_t getsid(pid_t pid); // 获取指定进程的 SID,(pid == 0)==> 当前进程
pid_t setsid(void); // 调用进程不能是进程组长
- 创建新会话,SID == PID,调用进程成为会话首进程
- 创建新进程组,PGID == PID,调用进程成为进程组长
- 调用进程没有控制终端,若调用前关联了控制终端,调用后与控制终端断联
3.2 实例
- 下面的程序输出什么?为什么?
【参看链接】:09 - Linux进程层次分析 / 04session / session.c
- 实验一
- 实验2