进程关系之终端登录

来源:互联网 时间:1970-01-01

在早期的UNIX系统中,用户用哑终端(用硬连接连到主机,更多关于哑终端:http://zh.wikipedia.org/wiki/%E5%93%91%E7%BB%88%E7%AB%AF)进行登录。终端要么是本地的(直接连接)要么是远程的(通过调制解调器连接)。在这两种情况下,登录都经由内核中的终端设备驱动程序

1、BSD终端登录

系统管理员创建通常名为/etc/ttys的文件,其中每个终端设备都有一行,每一行说明设备名和传递给getty程序的参数,例如,参数之一说明了终端的波特率等。当系统自举时,内核创建ID为1的进程,也就是init进程init进程使系统进入多用户状态init进程读文件/etc/ttys对每一个允许登录的终端设备,init调用一次fork它所生成的子进程则执行(exec)getty程序

getty为终端设备调用open函数,以读、写方式将终端打开。如果设备是调制解调器,则open可能会在设备驱动程序中滞留,直到用户拨号调制解调器,并且呼叫被应答。一旦设备被打开,则文件描述符0、1、2就被设置到该设备。然后getty输出“login:”之类的信息,并等待用户键入用户名。如果终端支持多种速度,则getty可以测试特殊字符以便适当地更改终端速度(波特率)。

当用户键入了用户名后,getty的工作就完成了。然后它以类似于下面的方式调用login程序

execle("/bin/login", "login", "-p", username, (char *)0, envp);

(在gettytab文件中可能会有一些选项使其调用其他程序,但系统默认的是login程序)。init以一个空环境调用getty。getty以终端名(例如TERM=foo,其中终端foo的类型取自gettytab文件)和在gettytab中说明的环境字符串为login创建一个环境(envp参数)。-p标志通知login保留传给它的环境,也可将其他环境字符串加到该环境中,但是不要替换它。

login能执行多项工作。因为它得到了用户名,所以能调用getpwnam取得相应用户的口令文件登录项。然后调用getpass(3)以显示提示“Password:”,接着读用户键入的口令(自然,禁止回送用户键入的口令)。它调用crypt(3)将用户键入的口令加密并与该用户在阴影口令文件中登录项的pw_passwd字段相比较。如果用户几次键入的口令都无效,则login以参数1调用exit表示登录过程失败。父进程(init)了解到子进程的终止情况后,将再次调用fork,其后接着执行getty,将对此终端重复上述过程。

这是UNIX系统传统的用户身份验证过程。现代UNIX系统已发展到支持多个身份验证过程。例如FreeBSD、Linux、Mac OS X以及Solaris都支持被称为PAM(Pluggable Authentication Module,可插入式身份验证模块)的更加灵活的方案。PAM允许管理员配置使用何种身份验证方法来访问那些使用PAM库编写的服务。

如果应用程序需验证一用户是否具有适当的权限去执行某个服务,那么我们可以将身份验证机制编写到应用中,或者使用PAM库来得到等价的功能。使用PAM的优点是,管理员可以基于本地策略、针对不同任务配置不同的验证用户身份的方法。

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

  • 将当前工作目录更改为该用户的起始目录(chdir)。
  • 调用chown改变该终端的所有权,使登录用户成为它的所有者。
  • 将对该终端设备的访问权限改变成用户读和写。
  • 调用setgid及initgroups设置进程的组ID。
  • 用login所得到的所有信息初始化环境:起始目录(HOME)、shell(SHELL)、用户名(USER和LOGNAME),以及一个系统默认路径(PATH)。
  • login进程改变为登录用户的用户ID(setuid)并调用该用户的登录shell(换一种容易理解的说法:login调用exec将其自身替换为登录用户的登录shell),如下:

execl("/bin/sh", "-sh", (char *)0);

到此为止,登录用户的登录shell开始运行。其父进程ID是init进程ID(进程ID 1),所以此登录shell终止时,init会得到通知(接到SIGCHLD信号),它会对该终端重复全部上述过程。将登录shell的文件描述符0、1和2设置为终端设备

现在,登录shell读取其启动文件(Bourne shell和Korn shell是:.profile;GNU Bourne-again shell是.bash_profile、.bash_login或.profile;C shell是.cshrc和.login)。这些启动文件通常会改变某些环境变量,加上很多环境变量。当执行完启动文件后,用户最后得到shell提示符,并能键入命令

2、Linux终端登录

Linux的终端登录过程非常类似于BSD。确实,Linux login命令是从4.3BSD login命令派生而来的。BSD登录过程与Linux登录过程的主要区别在于说明终端配置的方式。

在Linux中,/etc/inittab包含配置信息,它说明了init应当为之启动getty进程的各终端设备,这类似于系统V的方式。依赖于所使用的getty的版本,终端的各种特性要么在命令行上说明,要么在文件/etc/gettyefs中说明。

 

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/


相关阅读:
Top