《UNIX环境高级编程》笔记——进程(三)

本篇主要是进程关系相关知识。

一、Unix终端登录过程:

init----->init---->getty----->login----->getpwname----->getpasw----->crypt----->登录成功  

系统管理员创建通常名为/etc/ttys的文件,文件中每个终端设备都有一行用来说明设备名和传递给getty程序的参数<如终端的波特率等等>

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

2.  getty为终端设备调用open函数,以读写方式将终端打开。然后getty输出“longin:”之类的信息,并等待用户键入用户名。

3.  当用户键入用户名后,getty工作完成。然后调用login程序:

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

4.  Login确认口令,成功后将切换目录到用户的home目录,改变该终端设备的权限,login进程改变为登录用户ID并调用改用户的登录shell:execl(“/bin/sh”,”-sh”,(char *)0)

5. 登录shell读取其启动文件(Bourne shell)和Korn shell是:.profile;GNU Bourne-again shell是.bash_profile、.bash_login或.profile;C shell是.cshrc和.login。

 

网络登录:

与终端登录不同,有一个称为inetd的进程(有时称为Internet superserver),它等待大多数的网络连接。

系统启动时,init调用一个shell,使其执行shell脚本etc/rc,由此脚本启动一个精灵进程inetd,当此shell脚本终止,inetd的父进程就变成init。inetd等待TCP/IP连接请求到达主机。而当一个连接请求到达时,它执行一次fork,然后该子进程执行适当的程序。

 

二、进程组

进程组是一个或多个进程的集合,有一个唯一的进程组ID,通常,他们与同一作业相关联,可以接收来自同一终端的各种信号。

int  setpgid(pid_t pid, pid_t pgid);  //加入一个现有的组或创建一个组
pid_t  getpgrp(void);   //返回进程的进程组ID

每个进程组都有一个组长进程,组长进程的标识是其进程组IDD等于去其进程ID。只要某个进程组中有一个进程存在,则该进程组存在。

 

三、会话

会话是一个或多个进程组的集合。调用setsid函数就可以建立一个新的对话期。

   #include <sys/types.h>
   #include <unistd.h>
   pid_t setsid(void);

如果调用此函数的进程不是一个进程组的组长,则创建一个新会话。结果为:

(1)此进程变为新会话首进程。

(2)成为新进程组的组长进程。

(3)此进程没有控制终端。

如果此调用进程已经是一个组长进程,则此函数返回出错。为了保证不出现这种情况,通常fork一个子进程,然后使其父进程终止,而子进程继续。因为子进程继承了父进程的进程组ID,又绝对不会是组长进程。

 

四、控制终端

(1)一个会话可以有一个控制终端。

(2)建立和控制终端连接的会话首进程被称为控制进程

(3)一个会话中的几个进程组可被分为一个前台进程组以及一个或者多个后台进程组

(4)如果一个会话有一个控制终端,则它有一个前台进程组,会话中的其他进程组则为后台进程组

(5)无论何时键入终端的中断键(常常是DELETE或Ctrl+C),就会将中断信号发送给前台进程组的所有进程

(6)无论何时键入终端的退出键(常常是Ctrl+\),就会将退出信号发送给前台进程组中的所有进程

(7)如果终端接口检测到调制解调器已经断开连接,则将挂断信号发送给控制进程(会话首进程)。

 

五、作业控制

作业控制: 它允许一个在终端上启动多个作业(进程组),它控制哪一个作业可以访问该终端,以及哪些作业在后台运行。作业控制要求下面三种形式的支持:

(1)支持作业的shell

(2)内核中的终端驱动程序必须支持作业控制

(3)内核必须提供对某些作业控制信号的支持


我们可以键入一些特殊字符来影响前台作业:

1.中断字符(ctrl+c)产生SIGINT。

2.退出字符(ctrl+\)产生SIGQUIT。

3.挂起字符(ctrl+z)产生SIGTSTP。


键入这些字符后将信号送至前台进程组中的所有进程,后台进程组不受影响。

终端驱动程序必须处理与作业控制有关的另一种情况。我们可以有一个前台作业和若干个后台作业,这些作业中哪一个接受我们在终端上键入的字符呢?只有前台作业接受终端输入。如果后台作业试图读终端,那么这并不是一个错误,但是驱动程序将检测到这种情况,并且向后台作业发送一个特定信号SIGTTIN。该信号通常会暂停此后台作业,shell则向有关用户发出这种情况的通知,然后用户就可用shell命令将此作业转为前台作业运行,于是它就可以读终端了。

 

六、孤儿进程组

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

孤儿进程组:该组中每一个成员的父进程要么是该组的一个成员,要么不是该组所属会话的成员。换个表达方式,一个进程组不是孤儿进程组的条件是,该组中有一个进程,其父进程在属于同一会话的另一个组中。

一个进程组不是孤儿进程组的条件是:该组中有一个进程,其父进程在属于同一对话期的另一个组中。如果进程组不是孤儿进程组,则在属于同一对话期的另一个组中的父进程就有机会重新启动该组中停止的进程。


七、守护进程

1、概念

守护进程,也称精灵进程,是生存期较长的一种进程。它们常常在系统引导装入时启动,仅在系统关闭时才终止。它们没有控制终端,在后台运行。大多数守护进程的父进程是init进程。由于他没有控制终端,所以不能只是简单的写到标准出错上,需要有一个集中的守护进程出错记录设施syslog.

2、编程规则

1.调用umask将文件模式创建屏蔽字设置为0。因为由继承的来的文件模式创建屏蔽字可能会拒绝设置某些权限。

 2.调用fork,然后使父进程退出。这样做实现了下面几点:第一,如果该守护进程是作为一条简单shell命令启动的,那么父进程终止使得shell认为这几条命令已经执行完毕。第二,子进程继承了父进程的进程组ID,但具有一个新的进程ID,这就保证了子进程不是一个进程组的组长进程,这对于下面就是做的setsid调用是必要的前提条件。

3.调用setsid以创建一个新会话。使调用进程:a.成为新会话的首进程,b.成为一个新进程组的组长进程,c.没有控制终端。

4.将当前工作目录更改为根目录。

5.关闭不需要的文件描述符。这使守护进程不再持有从其父进程继承来的某些文件描述符。

6.某些守护进程打开/dev/null使其具有文件描述符0,1和2,这样,任何一个试图读标准输入,写标准输出或标准出错的库例程都不会产生任何效果。




 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值