读书笔记-APUE第三版-(9)进程关系

登录过程

终端登录

init从/etc/ttys中读取终端信息,对每个允许登录的终端,都fork子进程,并执行getty。getty打开终端设备,执行login:

execle(“/bin/login,“login”, “-p”, username, (char *)0, envp)

login进行用户名密码验证,同时还会进行切换到用户主目录/修改终端设备属主&读写权限/创建进程组/setuid等动作,然后运行login shell。

 execl(“/bin/sh”,“-sh”, (char*)0)

Login shell的标准输入、输出和错误输出都被设置为终端设备,login shell还会读取.bash_profile等初始化文件

网络登录

通过网络登录的最大不同是,终端和主机之间的连接不是点对点的。和FTP和SMTP等网络服务一样,网络登录也只不过是一种服务。

如图,系统通过inetd(xinetd)守护进程处理网络连接。假设用户在其他主机运行

telnet hostname

inetd 根据网络连接类型fork出子进程运行相应的telnetd程序。Telnetd会开启伪终端,并进行fork。父进程处理网络通信,子进程运行login程序,接下来流程和上一节介绍的通过终端登录一致。(伪终端和实际用户终端之间的通信细节后续章节介绍)

进程组

#include <unistd.h>
pid_t getpgid(pid_t pid);
int setpgid(pid_t pid, pid_t pgid);

进程组是一组进程的集合。进程通过调用setpgid方法创建或者加入进程组。如果进程ID和进程组ID相等,该进程被称之为组长(leader)。进程组的生命周期开始于创建,结束于组内最后一个进程终止(组长可能先挂掉没有关系)。在shell的作业控制过程中,父进程fork子进程后,都会调用setpgid方法,确保子进程加入进程组。

会话

会话是一组进程组的集合。如下图,会话中的进程组布局一般由shell管道产生:

proc1|proc2 & proc3|proc4|proc5

#include <unistd.h>
pid_t getsid(pid_t pid);
pid_t setsid(void);

进程调用setsid创建会话,该进程成为会话组长,同时创建了一个新的进程组,调用进程成为进程组组长。已经是进程组组长的进程调用setsid会失败,所以常见处理方式是父进程fork出子进程之后终止,让子进程创建会话,因为子进程的进程组ID继承自父进程,所以必定还不是组长。

控制终端

一个会话只能有一个控制终端。与控制终端建立连接的会话组长,称之为控制进程。前台进程组即拥有控制终端的进程组,中断信号(Control+C)会发送给前台进程组中的所有进程。

include <unistd.h> 45
pid_t tcgetpgrp(int filedes);
int tcsetpgrp(int filedes, pid_t pgrpid)

通过tcgetpgrp和tcsetpgrp可以获取和设置前台进程组。只有拥有控制终端的进程才能调用tcsetpgrp方法。这两个方法一般用于作业控制而不会被应用程序程序直接调用。

作业控制

一个作业(job)一般来讲是一组进程通过管道连接组成的进程组。命令行后加上&启动的就是后台作业。键入Ctrl+Z,发送SIGTSTP信号,可以将前台作业暂停并转为后台。只有前台作业能接收终端输入,后台作业试图读取终端输入时,终端驱动会发送SIGTTIN信号给后台作业,后台作业暂停,并在标准输出上报告作业状态。在mac上试了一把,输入fg视图让后台作业转为前台,挂了。。据说这是mac的bug。而后台作业输出到终端是没有问题的,但可以通过stty tostop命令禁止输出。

下图总结了会话中前台进程组、后台进程组和终端之间的交互关系。其中SIGTTOU信号发生于后台进程组想要进行输出时。

Shell运行程序

实验一下shell执行程序时和进程租,控制终端、会话和作业控制等概念的对应关系。

Mac不太灵,这次来看看Linux,首先是管道:

三个进程都属于同一个会话(26071);ps和cat都是bash(28629)的子进程,属于同一个前台进程组(17121),拥有控制终端,ps是组长;而bash单独属于一个进程组(28629)。

再试试后台作业:

最大的区别是拥有控制终端的前台进程组变为bash所在组。

最后验证一下连续管道,看来bash fork出了三个子进程。

孤儿进程组

当进程组中所有成员的父进程要么在该组中,要么不属于这个会话时(父进程提前挂掉的子进程会被init“收养”),这个进程组被称为孤儿进程组。系统将给孤儿进程组发送SIGHUP(默认行为是终止进程)和SIGCONT(继续运行)信号。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-22 17:24:36

读书笔记-APUE第三版-(9)进程关系的相关文章

读书笔记-APUE第三版-(7)进程环境

本章关注单进程运行环境:启动&终止.参数传递和内存布局等. 进程启动终止 如图所示: 启动:内核通过exec函数执行程序,在main函数运行之前,会调用启动例程(start-up routine),取得命令行参数和环境变量.可以把启动例程理解为exit(main(argc,argv)). 终止:五种正常终止方式(从main方法返回/exit/_exit/最后一个线程返回/最后一个线程退出):三种异常终止方式(abort/接收到信号/最后一个线程接收到取消请求). exit与_exit关系:exi

读书笔记-APUE第三版-(8)进程控制

进程ID 每一个进程都有一个唯一的进程ID.几个特殊进程: 0号进程是内核进程,一般是调度进程swapper. 1号进程init,是用户进程(以root权限执行/sbin/init),负责初始化. 几个重要函数:getpid(进程ID)/getppid(父进程ID)/getuid(进程真有用户ID)/geteuid(进程有效用户ID)/getgid(进程真有用户组ID)/getegid(进程有效用户组ID). fork/exec/wait例程 fork家族函数用于创建子进程(父子进程关系下节详细

读书笔记-APUE第三版-(5)标准IO库

ISO C标准I/O库使用流的概念读写文件.流是对数据传输的抽象,可以把流理解为从起点到终点间的字节序列. 标准I/O库通过维护进程空间内的缓冲区,减少read/write系统调用次数来提高I/O效率.之前介绍的Unbuffered I/O和文件描述符fd打交道,标准I/O则使用FILE指针. typedef struct{ short level;/*缓冲区满程度*/ unsigned flags;/*文件打开状态标志*/ char fd;/*文件描述符*/ unsigned char hol

读书笔记-APUE第三版-(6)系统数据文件和信息

常见系统数据文件 下表列出了常见的系统数据文件及其查找函数. 以/etc/passwd文件为例,读取数据的程序基本框架如下: void get_pw_entry() { struct passwd *ptr; setpwent(); while ((ptr = getpwent()) != 0) { -- } endpwent(); return ptr; } 每个数据文件都提供了一个get方法返回文件下一个记录项. set方法充值当前位置到文件开始处. end方法关闭数据文件. 表格中的get

【字源大挪移—读书笔记】 第三部分:字尾

[字源大挪移—读书笔记] 第三部分:字尾 [3 字尾:[3.1]名词字尾.[3.2]形容词字尾.[3.3]副词字尾.[3.4]动词字尾 [3.1]名词字尾(Noun) [3.1.1]表示[人]的字尾 -ain -aire -an -ian -ean -ese -ant -ent -ary -ate -ee {[备注]:和-er相反,表示"被……的人":} -eer -er -or -ar -ier -eur -ician -ist -ite -ive -man -on -ster -y

《众妙之门 JavaScript与jQuery技术精粹》 - 读书笔记总结[无章节版][1-60]

近期,反复思考后,还是把所有的笔记通过随笔的方式整理出来放在论坛里,可以让自己对学过的知识有个比较系统而清晰的呈现: 同时,为以后用到相关的知识点做一个整理和查阅. (一)JSON-P 的实例代码展示 1 <div id="delicious"></div> 2 <script type="text/javascript"> 3 // 可以在JavaScript中直接使用JSON,并且封装在函数调用中时,可作为API的返回值. 4

读书笔记-单元测试艺术(三)-使用桩对象解除依赖

一.几个概念 1.什么是外部依赖 外部依赖是指在系统中代码与其交互的对象,而且无法对其做人为控制. 最常见的例子是文件系统.线程.内存和时间等,我们使用桩对象来处理外部依赖问题. 2.什么是桩对象 桩对象是对系统中现有依赖的一个替代品,可人为控制. 通过使用桩对象,无需涉及依赖项,即可直接对代码进行测试. 3.什么是重构 重构是指不影响已有功能而改变代码设计的一种行为 4.什么是接缝 接缝是指代码中可以插入不同功能(如桩对象类)的地方. 二.解除依赖 抽象一个接口 namespace LogAn

4441数据结构读书笔记系列(三)

3.2 线性表的定义 线性表(List):零个或多个数据元素的有限序列. 元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继. 线性表强调是有限的. 在较复杂的线性表中,一个数据元素可以由若干个数据项组成. 3.4 线性表的顺序存储结构 线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素. 描述顺序存储结构需要三个属性: 存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置. 线性表的最大存储

大话数据结构读书笔记系列(三)线性表

    转载请注明来源:http://blog.csdn.net/u010194538/article/details/51001353 第3章线性表 3.2 线性表的定义 线性表(List):零个或多个数据元素的有限序列. 元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继. 线性表强调是有限的. 在较复杂的线性表中,一个数据元素可以由若干个数据项组成. 3.4 线性表的顺序存储结构 线性表的顺序存储结构,指的是用一段地址连续的