Linux操作系统中/sbin/init程序的执行过程

 
发布时间:2007.08.22 06:05     来源:赛迪网    作者:kit

当init启动后,它通过执行各种启动事务来继续引导进程(检查并监视文件系统,启动后台程序daemons,等等),直至完成用户所有操作环境的设置工作。这里主要涉及4个程序:init、getty(agetty)、login和shell程序。这4个程序之间的关系见下图所示。

init进程的主要任务是根据/etc/rc文件中设置的信息,执行其中设置的命令,然后根据/etc/inittab文件中的信息,为每一个允许登录的终端设备使用fork()创建一个子进程,并在每个新创建的子进程中运行agetty (getty)程序。而init进程则调用wait(),进入等待子进程结束状态。每当它的一个子进程结束退出,它就会根据wait()返回的pid号知道是哪个对应终端的子进程结束了,因此就会为相应终端设备再创建一个新的子进程,并在该子进程中重新执行agetty程序。这样,每个被允许的终端设备都始终有一个对应的进程为其等待处理。

在正常的操作下,init确定agetty正在工作着以允许用户登录,并且收取孤立进程。孤立进程是指那些其父辈进程已结束的进程;在Linux中所有的进程必须属于单棵进程树,所以孤立进程必须被收取。当系统关闭时,init负责杀死所有其它的进程,卸载所有的文件系统以及停止处理器的工作,以及任何它被配置成要做的工作。

getty程序的主要任务是设置终端类型、属性、速度和线路规程。它打开并初始化一个tty端口,显示提示信息,并等待用户键入用户名。该程序只能由超级用户执行。通常,若/etc/issue文本文件存在,则getty会首先显示其中的文本信息,然后显示登录提示信息(例如:plinux login: ),读取用户键入的登录名,并执行login程序。

为了能让init程序运行getty,/etc/inittab文件中必须含有getty(agetty)命令。/etc/inittab文件中有关agetty的内容例子见如下所示。

列表 3.1 poeigl-1.2中的inittab文件

# inittab for linux, poeigl 1.2

# format:

# ttyline:termcap-entry:getty-command

tty1:con80x60:/bin/agetty 9600 tty1

tty2:con80x60:/bin/agetty 9600 tty2

tty3:con80x60:/bin/agetty 9600 tty3

tty4:con80x60:/bin/agetty 9600 tty4

# tty5:con80x60:/bin/agetty 9600 tty5

# tty64:dumb:/bin/agetty 9600 tty64

# tty65:dumb:/bin/agetty -m -t60 2400 tty65

每个终端都有自己的getty命令。其中列出了tty1—tty4对应的登录项信息。以’#’开始的是注释行。第1列是所用终端设备名称,第2列是指定终端的类型,这里指定了终端类型是con80x60。第3列是所执行的命令及其参数。最后两行中的tty64和tty65对应连接在串行端口上的终端。

对于使用串行端口与主机直接相连的终端以及通过modem拨号连接的终端,Linux的agetty程序还有其它一些属性。如在读取登录名时自动调整tty的设置信息,例如奇偶校验位、檫除字符、行结束字符以及上档键字符等。可选择地从链接的Hayes兼容modem信息中检测出传输波特率。

/dev/inittab中每一项的参数格式与具体使用哪一种getty程序有关。目前一般常用的getty程序有如下几种:

1.agetty(有时直接称为getty):容易设置,无须配置文件。适用于直接连接的终端;

2.getty(getty_ps的一部分):适用于直接连接的终端;

3.mgetty:最适合于通过modem连接,也可用于直连;

4.uugetty:仅用于通过modem连接终端,是getty_ps软件包的部分;

5.mingetty:简单的getty。适用于控制台终端或虚拟终端;

6.fbgetty:适用于控制台或虚拟终端。

Redhat 9系统默认配置中带有mingetty和agetty两个程序。控制台或虚拟终端使用的是mingetty。对于实际的字符终端则一般使用agetty。因此在Redhat 9系统的/etc/inittab文件中会看到以下的信息。

列表 3.2 RedHat 9系统的/etc/inittab文件中有关getty的信息

# Run gettys in standard runlevels

1:2345:respawn:/sbin/mingetty tty1

2:2345:respawn:/sbin/mingetty tty2

3:2345:respawn:/sbin/mingetty tty3

4:2345:respawn:/sbin/mingetty tty4

5:2345:respawn:/sbin/mingetty tty5

6:2345:respawn:/sbin/mingetty tty6

其中第1列表示名称tty后的数字,2345表示该mingetty的运行层。respawn表示如果该mingetty被终止,则mingetty将再次自动执行。/sbin/mingetty是命令。ttyn代表/dev/ttyn(n表示数字1—5)。

在登录到Linux系统中之后,你会发现(使用”top”或”ps –ax”命令)自己终端原来的getty进程已经找不到了。因为getty进程执行了login程序,被替换成了login进程,并且最后被替换成你的登录shell进程。

当你在”login: “提示符下键入了你的用户名后,getty会读取用户名并且去执行login程序,也把用户名信息传给了它。因此getty进程被替换成了login进程。此时login进程会接着要求你输入口令。在口令检查通过后就会去执行/etc/passwd文件中对应你用户名项中记录的程序。通常这个程序是bash shell程序。因此原来的getty进程最终被替换成了bash进程,对应的这三个程序也就都具有相同的进程ID。

当注销登录(log out)时,则该终端上的所有进程都会被终止(killed),包括登录shell进程bash。因此,对于在/etc/inittab文件中列出的getty程序,一旦其被替换执行的bash程序被终止或退出,init进程就会为对应终端重新创建一个getty进程。

login程序则主要用于要求登录用户输入密码。根据用户输入的用户名,它从口令文件passwd中取得对应用户的登录项,然后调用getpass()以显示”password:”提示信息,读取用户键入的密码,然后使用加密算法对键入的密码进行加密处理,并与口令文件中该用户项中pw_passwd字段作比较。如果用户几次键入的密码均无效,则login程序会以出错码1退出执行,表示此次登录过程失败。此时父进程(进程init)的wait()会返回该退出进程的pid,因此会根据记录下来的信息再次创建一个子进程,并在该子进程中针对该终端设备再次执行agetty程序,重复上述过程。

login程序也可以被用户在运行过程中在shell下当作一个命令执行。此时它可以被用随时从一个用户切换成另一个用户。如果执行时没有给出参数,则login就会显示输入用户名的提示信息。如果用户不是超级用户(root),并且/etc/目录下存在一个名为nologin的文件,那么该文件中的信息就会被显示出来,此次登录过程也随即被终止。

如果在/etc/usertty文件中对该用户指定了特殊的访问限制,那么这些限制要求必须满足。如果是一个超级用户,那么所使用的登录tty设备必须是在/etc/securetty文件中指定的。

在所有这些条件满足之后,login同样也会要求用户输入密码并对其进行检查。如果.hushlogin存在的话,login就会执行一个“安静”的登录过程,也即不检查是否有邮件,也不显示上次登录时间和motd文件中的信息。否则如果/var/log/lastlog文件存在的话,就会显示其中的最后登录时间。

如果用户键入的密码正确,则login就会把当前工作目录(Currend Work Directory)修改成口令文件中指定的该用户的起始工作目录。并把对该终端设备的访问权限修改成用户读/写和组写,设置进程的组ID。然后利用所得到的信息初始化环境变量信息,例如起始目录(HOME=)、使用的shell程序(SHELL=)、用户名(USER=和LOGNAME=)和系统执行程序的默认路径序列(PATH=)。接着显示/etc/motd文件(message-of-the-day)中的文本信息,并检查并显示该用户是否有邮件的信息。最后login程序改变成登录用户的用户ID并执行口令文件中该用户项中指定的shell程序,如bash或csh等。

如果口令文件/etc/passwd中该用户项中没有指定使用哪个shell程序,系统则会使用默认的/bin/sh程序。如果口令文件中也没有为该用户指定用户起始目录的话,系统就会使用默认的根目录/。有关login程序的一些执行选项和特殊访问限制的说明,请参见Linux系统中的在线手册页(man 8 login)。

Shell程序是一个复杂的命令行解释程序,是当用户登录系统进行交互操作时执行的程序。它是用户与计算机进行交互操作的地方。它获取用户输入的信息,然后执行命令。用户可以在终端上向shell直接进行交互输入,也可以使用shell脚本文件向shell解释程序输入。在Linux系统中,目前常用的shell有:

Bourne Again Shell,/bin/bash

C shell,/bin/csh(或tcsh)

BSD shell/bin/ash(或bsh)

在登录过程中,系统(login)会从口令文件用户对应登录项的最后一个字段知道应该为用户执行哪个shell程序。

shell程序中实现了一个具有流控制结构的语言,使用相当广泛。目前这些shell程序都朝着与IEEE POSIX 1003.2兼容的方向发展,因此它们各自虽然各自有自己的特点,但基本功能已经越来越相象。本书主要介绍bash的工作原理和实现机制,其它几种shell的实现机制与之类似。

在登录过程中login开始执行shell时,所带参数argv[0]的第一个字符是’-’,表示该shell是作为一个登录shell被执行。此时该shell程序会根据该字符,执行某些与登录过程相应的操作。登录shell会首先从/etc/profile文件以及.profile文件(若存在的话)读取命令并执行。如果在进入shell时设置了ENV环境变量,或者在登录shell的.profile文件中设置了该变量,则shell下一步会从该变量命名的文件中读去命令并执行。因此用户应该把每次登录时都要执行的命令放在.profile文件中,而把每次运行shell都要执行的命令放在ENV变量指定的文件中。设置ENV环境变量的方法是把下列语句放在你起始目录的.profile文件中。

ENV=$HOME/.anyfilename; export ENV

在执行shell时,除了一些指定的可选项以外,如果还指定了命令行参数,则shell会把第一个参数看作是一个脚本文件名并执行其中的命令,而其余的参数则被看作是shell的位置参数($1、$2等)。否则shell程序将从其标准输入中读取命令。

在执行shell程序时可以有很多选项,请参见Linux系统中的有关sh的在线手册页中的说明。

(责任编辑:云子)

时间: 2024-10-26 10:09:02

Linux操作系统中/sbin/init程序的执行过程的相关文章

Linux操作系统中FastDFS部署手册

关于Linux操作系统中FastDFS部署手册 1.       部署环境 关于本次FastDFS_3.11版本的部署实验环境如下表所示: FastDFS部署环境 类别 OS FastDFS 机器台数 备注 版本 RedHat_Linux.5.4-x86_64 FastDFS_v3.11 2 表格 1 2.       组件和包安装 安装开发工具和所需的开发包 配置yum升级服务或安装系统时选择安装相关的依赖组件,这里使用yum对包进行安装,如下所示: yum groupinstall-y "d

Linux操作系统中的系统调用接口函数

在分析病毒样本时发现有些系统函数是必用,有些超常用,现在都列出来,希望和大家交流 转载请注明出处:http://blog.csdn.net/u010484477     O(∩_∩)O谢谢 进程控制 fork 创建一个新进程 clone 按指定条件创建子进程 execve 运行可执行文件 exit 中止进程 _exit 立即中止当前进程 getdtablesize 进程所能打开的最大文件数 getpgid 获取指定进程组标识号 setpgid 设置指定进程组标志号 getpgrp 获取当前进程组

关于linux操作系统中进程相关问题的学习笔记

关于linux操作系统中进程相关问题的学习笔记 1.摘要   进程的经典定义是一个执行中程序的实例.系统中的每个程序都运行在某个进程的上下文中(contest)中.上下文是由程序运行正确运行所需的状态组成的.这个状态包括存放在内存中的程序的代码和数据,它的栈.通用目的寄存器的内容.程序计数器.环境变量以及打开文件描述符合的集合.在本次学习笔记中,我是以linux为例,学习了以下三个方面的知识:操作系统如何组织进程.进程状态如何转换以及进程是如何调度的.在最后我还谈了下自己对操作系统进程模型的一些

Linux操作系统中“rpm”命令的详细介绍

Linux中常见的软件包封装类型如下所述: RPM软件包:这种软件包的扩展名为 ".rpm" ,只能在使用RPM机制的Linux操作系统中安装,如RHEL.Fedora.centOS等.RPM软件包一般针对特定版本的操作系统量身定制,因此依赖性较强. 源代码安装包:这种软件包是程序员开发完成的原始代码,一般被制作成 ".tar.gz" 或 ".tar.bz2" 等格式的压缩包文件,因多数使用 tar 命令打包而成的,所以经常被称为 "t

针对Linux操作系统中root用户无法登陆的解决方案

在Linux操作系统中,当我们使用字符界面操作时,往往不经意间会遇到root用户无法正常登陆的情况.一般对于初学者来说,看到这种情况发生,简直就是要了命了,很多人在这时就开始慌了神,怎么办?重装系统吧! Linux真特么不好用,好麻烦!哈哈~当然不是啦,只是你还不熟悉罢了!今天我就告诉大家如何通过进入单用户模式来修改root用户的密码(不用重装系统哦!) 下面以CentOS系列操作系统为例: 第一步:Linux开机引导时,按一下键盘上的 e 就可以进入到grub菜单界面 第二步:当电脑上出现gr

C程序编译执行过程

C程序编译执行过程 认识C编译执行过程,是C学习的开端. 简单说C语言从编码编译到执行要经历一下过程: C源代码 编译---->形成目标代码,目标代码是在目标机器上运行的代码. 连接---->将目标代码与C函数库相连接,并将源程序所用的库代码与目标代码合并,并形成最终可执行的二进制机器代码(程序). 执行----->在特定的机器环境下运行C程序. 如果用一个图 来表示: 以上过程仅仅是个大概,详细的过程相当复杂,下面这篇文章写得很详细,从中受益很多: 原文来自:http://www.vc

Java异常处理机制就是程序代码执行过程

我也是通过各种方式在进行验证是否可以满足我们的需求,今天我就发现了一个问题.现在我们来一起说明一下,这个可能不算是bug,而应该需要我们记住就可以了. 对于一副灰度图像I,她的每一个像素点I(x,y)都有一个灰度值,一般情况下可能的灰度取值有2^8=256个(0,1,...,255).如果我们统计出灰度值r在I中出现的次数n,并对其进行归一化(n/N,N是所有灰度值出现次数的总和),这样我们就可以得到像素r在I中出现的概率p(r).如果对每一个可能的灰度取值r都做同样的处理,我们可以得到如图1左

说说Python程序的执行过程

1. Python是一门解释型语言? 我初学Python时,听到的关于Python的第一句话就是,Python是一门解释性语言,我就这样一直相信下去,直到发现了*.pyc文件的存在.如果是解释型语言,那么生成的*.pyc文件是什么呢?c应该是compiled的缩写才对啊! 为了防止其他学习Python的人也被这句话误解,那么我们就在文中来澄清下这个问题,并且把一些基础概念给理清.   2. 解释型语言和编译型语言   计算机是不能够识别高级语言的,所以当我们运行一个高级语言程序的时候,就需要一个

Linux树莓派中/etc/rc.local不执行的问题

最近研究在树莓派中嵌入式开发java程序,并打算和Salesforce进行通信.需要开发一个java的web server,不想弄那么复杂,于是打算在linux系统中/etc/rc.local写想要执行的语句,比如java –jar /root/test.jar.但是在开机的时候,发现/etc/rc.local里面的命令并没有执行,这是个头疼的事情.第一次我考虑到的是,可能在里面的某些语句,比如service isc-dhcp-server start.这类开启服务的语句,如果dhcp服务在ho