登录过程
终端登录
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(继续运行)信号。
版权声明:本文为博主原创文章,未经博主允许不得转载。