Skip to content
This repository was archived by the owner on Feb 1, 2022. It is now read-only.

Latest commit

 

History

History
194 lines (145 loc) · 5.97 KB

notes.md

File metadata and controls

194 lines (145 loc) · 5.97 KB

第09章 进程关系

章节目录 函数表


终端登录

待填坑

网络登录

待填坑

进程组

  • 进程组是一个或多个进程的集合,通常是在同一个作业中结合起来的。
  • 每个进程除了有一个进程ID之外,还属于一个进程组。
  • 同一进程组中的各进程接收来自同一终端的各种信号。
  • 每个进程组有一个唯一的ID:进程组ID。
#include <unistd.h>

pid_t getpgrp(void);
功能返回调用进程的进程组IDpid_t getpgid(pid_t pid);
返回值返回进程pid的进程组ID出错返回-1getpgid(0) 等同于 getpgrp()。
  • 每个进程组有一个组长进程,组长进程的进程组ID等于其PID。
  • 组长进程可以创建进程组、创建该组中的进程,然后终止。
  • 进程组的存在,与组长进程是否终止无关。只要进程组中有一个进程存在,该进程组就存在。
  • 进程组的生命期:从进程组创建开始,到其中最后一个进程离开为止。
  • 进程组的最后一个进程可以终止,也可以转移到另外一个进程组。
#include <unistd.h>

int setpgid(pid_t pid, pid_t pgid);
返回值成功返回0出错返回-1功能加入一个现有的进程组或者创建一个进程组形参说明将pid进程的进程组ID设置为pgidpid == pgid : pid指定的进程变成进程组组长pid == 0    : 使用调用者的 pidpgid == 0   : 由pid指定的进程ID用作进程组ID1 一个进程只能为自己或自己的子进程设置进程组ID
2 子进程调用了exec后父进程不能更改子进程的进程组ID
  • waitpid 函数可被用来等待指定进程组中的一个进程终止。

会话

会话,session,是一个或多个进程组的集合。

#include <unistd.h>

pid_t setsid(void);
返回值成功返回进程组ID若出错返回-1功能如果调用此函数的进程不是进程组组长则创建一个新会话如果调用进程是进程组组长则返回出错

创建新会话的动作:

  • 调用进程变成新会话的会话首进程。该进程是会话中的唯一进程。
  • 调用进程成为一个新进程组的组长,pgid = pid。
  • 该进程没有控制终端,如果调用之前有,也会被切断联系。

技巧:防止调用出错,通常调用fork,父进程结束,子进程继续。

#include <unistd.h>

pid_t getsid(pid_t pid);
返回值成功返回会话首进程的进程组ID出错返回-1功能返回会话首进程的进程组ID形参说明pid == 0: 返回调用进程的会话首进程的进程组IDpid 不属于调用者所在的会话将会返回出错。(某些实现

控制终端

会话和进程组的一些特性:

  • 一个会话可以有一个控制终端。通常是终端设备或伪终端设备。
  • 建立与控制终端连接的会话首进程被称为控制进程
  • 一个会话中的进程组,可被分为一个前台进程组,一个或多个后台进程组。
  • 如果一个会话有一个控制终端,则它有一个前台进程组,其余为后台进程组。
  • 在终端键入的任何输入,以及中断信号、退出信号,都会被发送到前台进程组。
  • 终端的挂断信号,会被发送到控制进程。

保证程序能与控制终端对话的方法是open文件 /dev/tty 。

关于getpass,终端回显被关闭的部分,没看懂。

函数tcgetpgrp、tcsetpgrp、tcgetsid

#include <unistd.h>

pid_t tcgetpgrp(int fd);
返回值返回前台进程组ID若出错返回-1int tcsetpgrp(int fd, pid_t pgrpid);
返回值成功返回0出错返回-1功能将前台进程组ID设置为pgrpid形参说明fd该会话的控制终端pgrpid前台进程组ID
#include <termios.h>

pid_t tcgetsid(int fd);
功能返回会话首进程的进程组ID出错返回-1形参fd控制TTY的文件描述符

作业控制

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

支持作业控制的条件:

  • 支持作业控制的shell
  • 内核中的终端驱动程序必须支持作业控制
  • 内核必须提供对某些作业控制信号的支持

从用户的角度看作业控制:用户可以在前台或后台启动一个作业。

  • 在后台启动作业,只需在命令的结尾加上&
  • 启动后台作业时,shell会返回一个作业标识符,并打印一个或多个进程ID。
  • 使用命令 fg %作业编号 可将作业从后台切换到前台。
  • 当后台作业完成并键入回车时,shell通知作业已经完成。
  • 有3个特殊字符可使终端产生信号,并发送至前台进程组:
  • 中断字符产生SIGINT,一般是Delete或Ctrl+C
  • 退出字符产生SIGQUIT,一般是Ctrl+\
  • 挂起字符产生SIGTSTP,一般是Ctrl+Z

终端IO与前后台作业:

  • 只有前台作业接收终端输入。
  • 后台作业尝试读取终端,会收到信号SIGTTIN,并且shell会通知用户。
  • 只有前台进程可以输出到终端。
  • 后台进程尝试输出到终端,会收到信号SIGTTOU,并且shell会通知用户。

    用户收到通知后,可用命令fg,将作业转为前台。

shell执行程序

shell是如何执行程序的,以及这与进程组、控制终端和会话等概念的关系。

暂时没看太懂,待填坑。

孤儿进程组

待填坑

FreeBSD实现

待填坑


章节目录 函数表