UNIX高级环境编程读书笔记(chapter9)

来源:互联网 发布:电影配乐知乎 编辑:程序博客网 时间:2024/05/19 19:31

chapter 9进程关系

          当系统自举时,内核创建进程ID为1的进程,Init进程。Init进程使系统进入多用户状态。Init进程读文件/etc/ttys,对每一个允许登陆的终端设备,Init调用一次fork,它所生成的子进程则执行getty程序。

getty为终端设备调用open函数,以读写方式将终端打开。一旦设备被打开,则文件描述符0、1、2就被设置到该设备。然后getty输出“login:”之类的信息,并等待用户键入用户名。

login能执行多项工作。因为它得到了用户名,所以能调用getpwname取得相应用户的口令文件登陆项。然后调用getpass(3)以提示“Password”,接着读用户键入的口令。

如果用户正确登陆,login就将执行如下工作:

(1)将当前工作目录更改为该用户的起始目录(chdir)。

(2)调用chown改变该终端的所有权,使登陆用户成为它的所有者。

(3)将对该终端设备的访问权限改变成用户读和写。

(4)调用setgid及initgroups设置进程的组ID。

(5)用login所得到的所有信息初始化环境:起始目录(HOME),shell(SHELL)、用户名(USER和LOGNAME),以及一个系统默认路径(PATH).

(6)login进程改变为登陆用户的用户ID(setuid)并调用该用户的登陆shell。

    在linux中,/etc/inittab包含配置信息:

Default runlevel. The runlevels used by RHS are:

#   0 - halt (Do NOT set initdefault to this)

#   1 - Single user mode

#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)

#   3 - Full multiuser mode

#   4 - unused

#   5 - X11

#   6 - reboot (Do NOT set initdefault to this)


网络登陆:

在这种情况下,login只是一种可用的服务,这与其他网络服务(例如FTP或SMTP)的性质相同。

为使同一个软件既能处理终端login,又能处理网络login,系统使用了一种称为伪终端的软件驱动程序,它仿真串行终端的运行行为,并将终端操作映射为网络操作,反之亦然。


进程组:

每个进程除了有一个进程ID之外,还属于一个进程组。

进程组是一个或多个进程的集合。每个进程组都可以有一个组长进程。组长进程的标识是,其进程组ID等于其进程ID。进程可以通过调用setpgid来加入一个现有的组或者创建下一个进程组。


会话

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


shell执行程序:

ps -o pid,ppid,pgid,sid,comm

  #PID  PPID  PGID   SID COMMAND
  4887  4884  4887  4887 bash

  4887  4884  4887  4887 bash

  5881  4887  5881  4887 ps

ps命令的父进程是shell,这正是我们所期望的。shell和ps命令两者位于同一会话和前台进程组中。

如果在后台执行该命令:

#ps -o pid,ppid,pgid,sid,comm &

PID  PPID  PGID   SID COMMAND

4887  4884  4887  4887 bash

          6027  4887  6027  4887 ps

则唯一改变的值是命令的进程ID。

孤儿进程组:

一个其父进程已终止的进程称为孤儿进程,这种进程由init进程“收养”。

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

实例:创建一个孤儿进程组

#include "apue.h"#include <errno.h>static void sig_hup(int signo){    printf("SIGUP received, pid = %d\n", getpid());}static void pr_ids(char *name){    printf("%s: pid = %d, ppid = %d, pgrp = %d, tpgrp = %d\n",                    name, getpid(), getppid(), getpgrp, tcgetpgrp(STDIN_FILENO));    fflush(stdout);}int main(void){    char c;    pid_t pid;    pr_ids("parent");    if ((pid = fork()) < 0)    {        err_sys("fork error");    }else if (pid > 0)    {        sleep(5);        exit(0);    }else    {        pr_ids("child");        signal(SIGHUP, sig_hup);        kill(getpid(), SIGTSTP);        pr_ids("child");        if (read(STDIN_FILENO, &c, 1) != 1)        {            printf("read error from controlling TTY, errno = %d\n", errno);        }        exit(0);    }}


parent: pid = 14555, ppid = 14481, pgrp = 134514244, tpgrp = 14555
child: pid = 14556, ppid = 14555, pgrp = 134514244, tpgrp = 14555
SIGUP received, pid = 14556
child: pid = 14556, ppid = 1, pgrp = 134514244, tpgrp = 14555

0 0
原创粉丝点击