Apue.2e Chapter9 Process relations

终端登录过程:

init读取/ect/ttys,对每一个允许登陆的中断设备fork一次,子进程执行getty程序,getty为终端设备调用open函数(read | write),打开后设置filedes 0,1,2;getty输出login等待用户输入用户名,然后调用login程序(execle传入环境变量)。后者使用getpwnam获得用户口令登陆项,再调用getpass显示提示符提示用户输入密码,然后用crypt将输入的口令加密,再与阴影口令文件中的pw_passwd字段作比较,确定密码的正确性。如果错误,调用exit离开;如果正确,chdir,chown,chmod,setgid,initgroups,setuid,execl /bin/sh,初始化环境变量等等,shell会读取启动文件,然后才能输出shell提示符。

现代UNIX系统支持PAM(可插入式身份验证模块),允许admin配置身份验证方法。

网络登陆:

init调用一个shell,然后执行/etc/rc,启动守护进程inetd,该进程等待TCP/IP请求到达主机,然后fork并执行适当的进程。这里使用了伪终端来模拟login的登陆过程,父进程处理网络通信,子进程则执行login程序(同传统登陆)。

进程组:

pid_t getpgrp(void);

pid_t getpgid(pid_t pid);

int setpgid(pid_t pid,pid_t pgid);

进程组id是创建该进程组的进程的id,也就是组长id。

注意:一个进程只能为自己或子进程设置pid,一旦在子进程中调用了exec系函数,就不能再改变进程组id。为防止竞争条件,往往在父子进程fork后都执行一次setpgid(冗余一次)。

会话(session):

会话是进程组的集合,会话id是非Posix的,只有会话首进程(session leader)id,也就是创建会话的进程的id。

pid_t getsid(pid_t pid);

如果pid是0,返回调用进程的会话首进程的进程组的pid。如果pid不属于调用者所在的会话,返回错误。

pid_t setsid(void);

建立新会话,如果调用该函数的进程已经是一个进程组的组长,则调用失败。新建的绘画没有控制终端。

控制终端:

会话的非必需关联物,前台进程组是正在控制终端中运行的进程组,后台则相反。

可以通过以下函数获得前台进程组:

pid_t tcgetpgrp(int filedes);

int tcsetpgrp(int filedes, pid_t pgrpid);

注意:pgrpid必须是同一会话中的进程组的id;

作业控制:

这部分主要讲了常见的作业控制方法(前台、后台等),以及终端驱动程序如何与之交互。

使用stty可以改变作业控制相关的输出方式;

shell执行程序:

具有作业控制和不具有作业控制的shell执行管道命令的方式不同。

具有作业控制的shell会将前台作业放入它自己的进程组(和shell不同),而不具有作业控制的则相同。

孤儿进程组:

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

在父进程终止后,Posix.1要求向新的孤儿进程组中处于停止状态的每一个进程发送挂断信号(SIGHUP),接着又向其发送继续信号。

最后讲了FreeBSD的实现。

posted @ 2013-02-02 17:11  生无所息  阅读(246)  评论(0编辑  收藏  举报