9 - 进程关系

GitHub 地址


1. 进程组

每个进程除了有一个 进程 ID 外,还属于一个 进程组 。进程组是一个或多个进程的 集合 ,通常,它们是在同一作业中结合起来的,同一进程组中的各进程接受来自同一终端的各种信号。每一个进程组有一个唯一的 进程组 ID

函数 getpgrp 返回调用进程的进程组 ID:

#include <unistd.h>
pid_t getpgrp(void); //返回值:调用此函数的进程的进程组ID

函数 getpgid 用于获取指定 \(pid\) 进程的进程组 ID:

#include <unistd.h>
pid_t getpgid(pid_t pid); //返回值:若成功,返回进程组ID;若出错,返回-1

getpgid(0) 等价于 getpgrp()

每个进程有一个 组长进程 ,组长进程的进程组 ID ,等于其进程 ID 。进程组组长可以创建一个进程组、创建该组中的进程,然后终止。只要在某个进程组中有一个进程存在,则该进程组就存在,与组长进程是否终止无关。从进程组创建开始到其中最后一个进程离开为止的时间区间称为 进程组的生命期

进程调用 setpgid 可以加入一个现有的进程组或创建一个新进程组:

#include <unistd.h>
int setpgid(pid_t pid, pid_t pgid); //返回值:若成功,返回0,;若出错,返回-1
  • setpgid 将 \(pid\) 进程组ID 设置为 \(pgid\)
  • 如果这两个参数相等,则由 \(pid\) 指定的进程变成进程组组长
  • 如果 \(pid\) 是 \(0\) ,则使用调用者的进程ID
  • 如果 \(pgid\) 是 \(0\) ,则由 \(pid\) 指定的 进程ID 用作 进程组ID

一个进程只能为 它自己或它的子进程 设置进程组ID。在它的子进程调用 exec 后,它就不再更改该子进程的进程组 ID。

2. 会话

会话 (session) 是一个或多个进程组的集合。通常是shell的 管道 将几个进程编成一组的。

进程调用 setsid 函数建立一个新会话:

#include <unistd.h>
pid_t setsid(void); //返回值:若成功,返回进程组ID;若出错,返回-1.
  • 如果调用此函数的进程不是一个进程组的组长,则此函数会创建一个新会话。具体会发生:

    1. 该进程编成新会话的 会话首进程 (会话首进程是创建该会话的进程) ,此时,该进程是新会话中的唯一进程。
    2. 该进程成为一个新进程组的组长进程。新进程组ID是该调用进程的进程 ID。
    3. 该进程没有控制终端。如果在调用 setsid 之前该进程有一个控制终端,那么这种联系也被切断。
  • 如果该调用进程已经是一个进程组的组长,则此函数返回出错。

getsid 函数返回 会话首进程的进程组ID (可理解为会话ID)

#include <unistd.h>
pid_t getsid(pid_t pid); //返回值:若成功,返回会话首进程的进程组ID;若出错,返回-1

若 \(pid=0\) ,getsid 返回 调用进程 的会话首进程的进程组ID 。

getsid 函数有如下限制:若 \(pid\) 并不属于调用者所在的会话,那么调用进程就不能得到该会话首进程的进程组ID 。

3. 控制终端

  • 一个会话可以有一个 控制终端 。这通常是终端设备(在终端登录情况下)或伪终端设备(在网络登录情况下)。
  • 建立与控制终端连接的会话首进程被称为 控制进程
  • 一个会话中的几个进程可被分成一个 前台进程组 以及一个或多个 后台进程组
  • 如果一个会话有一个控制终端,则它有一个前台进程组,其他进程组为后台进程组。
  • 无论何时键入终端的 中断键 ,都会将 中断信号 发送至前台进程组的所有进程 。
  • 无论何时键入终端的 退出键 ,都会将退出信号发送至前台进程组的所有进程。
  • 如果终端接口检测到调制解调器(或网络)已经断开连接,则将挂断信号发送至 控制进程(会话首进程)

4. 函数 tcgetpgrp、tcsetpgrp 和 tcgetsid

#include <unistd.h>
pid_t tcgetpgrp(int fd); //返回值:若成功,返回前台进程组ID;若出错,返回-1
int tcsetpgrp(int fd, pid_t pgrpid); //返回值:若成功,返回0;若出错,返回-1
#inlcude <termios.h>
pid_t tcgetsid(int fd); //返回值:若成功,返回会话首进程的进程组ID;若出错,返回-1

\(fd\) 为 控制终端的文件描述符

tcsetpgrp 函数将前台进程组ID设置为 \(pgrpid\) 。\(pgrpid\) 值应当是在同一会话中的一个进程组的 ID。

5. 作业控制

一个 作业 即一个进程组。UNIX 允许在一个终端上启动多个作业(进程组),它控制哪一个作业可以访问该终端以及哪些作业在后台运行。

& 放在命令后面表示设置此进程为后台进程。当启动一个后台作业时,shell 赋予它一个作业标识符,并打印一个或多个进程 ID。

有 \(3\) 个 特殊字符 可使终端驱动程序产生信号,并将它发送至前台进程组:

  • 中断字符(一般采用 Delete 或 Ctrl+C )产生 SIGINT
  • 退出字符(一般采用 Ctrl+\ )产生 SIGQUIT
  • 挂起字符(一般采用 Ctrl+Z )产生 SIGTSTP

fg 命令可将后台作业转为前台作业,如:fg %1

6. shell 执行程序

对于使用了 管道 的命令,该管道中的 最后一个进程是 shell 的子进程 ,而执行管道中 其他命令的进程则是该最后进程的子进程

如:ps -o pid,ppid | cat1 | cat2cat2 是 shell 的子进程,cat1pscat2 的子进程。

7. 孤儿进程组

定义 为:该组中每个成员的父进程要么 是该组的一个成员 ,要么 不是该组所属会话的成员

一个进程组不是孤儿进程组的条件是:该组中有一个进程,其父进程在属于 同一会话另一个组 中。如果进程组不是孤儿进程组,那么在属于同一会话的另一个组中的父进程就有机会重新启动该组中停止的进程。

《UNIX环境高级编程》(APUE) 笔记第九章 - 进程关系的更多相关文章

  1. 《UNIX环境高级编程》第七章进程环境

    7.2 main函数 1.C程序总是从main函数开始执行的,原型:int main(int argc,char *argv[]);argc是命令行参数的个数argc是指向参数的各个指针所构成的数组2 ...

  2. (十三) [终篇] 一起学 Unix 环境高级编程 (APUE) 之 网络 IPC:套接字

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  3. (六) 一起学 Unix 环境高级编程 (APUE) 之 进程控制

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  4. (七) 一起学 Unix 环境高级编程(APUE) 之 进程关系 和 守护进程

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  5. (八) 一起学 Unix 环境高级编程 (APUE) 之 信号

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  6. Unix 环境高级编程 (APUE) 之 网络 IPC:套接字

    一起学 Unix 环境高级编程 (APUE) 之 网络 IPC:套接字 . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级 ...

  7. (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  8. (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  9. (九) 一起学 Unix 环境高级编程 (APUE) 之 线程

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

随机推荐

  1. Linux(二) 系统远程访问

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1. Why?为什么需要远程访问? 人和人之间对话有两种方式,一种是面对面直接交谈,另一种是打电话. 我 ...

  2. Java实现 LeetCode 376 摆动序列

    376. 摆动序列 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列.第一个差(如果存在的话)可能是正数或负数.少于两个元素的序列也是摆动序列. 例如, [1,7,4,9,2,5 ...

  3. Java实现 LeetCode 334 递增的三元子序列

    334. 递增的三元子序列 给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列. 数学表达式如下: 如果存在这样的 i, j, k, 且满足 0 ≤ i < j < k ...

  4. Java实现 LeetCode 299 猜数字游戏

    299. 猜数字游戏 你正在和你的朋友玩 猜数字(Bulls and Cows)游戏:你写下一个数字让你的朋友猜.每次他猜测后,你给他一个提示,告诉他有多少位数字和确切位置都猜对了(称为"B ...

  5. Java实现LeetCode_0007_ReverseInteger

    package javaLeetCode_primary; import java.util.Scanner; /** * Given a 32-bit signed integer, reverse ...

  6. vi命令总结

    VI常用技巧 ​ VI命令可以说是Unix/Linux世界里最常用的编辑文件的命令了,但是因为它的命令集众多,很多人都不习惯使用它,其实您只需要掌握基本命令,然后加以灵活运用,就会发现它的优势,并会逐 ...

  7. Java培训Day02——制作疫情地图(一)

    一.前言 此次培训,是为期三天的网上培训.最终的目的是制作出疫情地图.首先我们来看看主要的讲课内容大纲. Day1 |-Java语法学习(个人感觉讲得还可以,主要围绕本次培训作出的讲解,没有像网上的基 ...

  8. tensorflow2.0学习笔记

    今天我们开始学习tensorflow2.0,用一种简单和循循渐进的方式,带领大家亲身体验深度学习.学习的目录如下图所示: 1.简单的神经网络学习过程 1.1张量生成 1.2常用函数 1.3鸢尾花数据读 ...

  9. 2.keras-构建基本网络实现非线性回归

    构建基本网络实现非线性回归 1.加载显示数据集 import tensorflow as tf import numpy as np import keras from keras.layers im ...

  10. Flask 的配置文件

    Flask 的配置文件 四种方法给 Flask 做配置 1直接给 app 对象赋值属性 以字典的形式,给flask做配置 以文件的形式,给flask做配置(django 就是用这种) 以类的形式,给f ...