Linux⽂件系统启动过程及login的实现(busybox)
1. busybox简介
busybox是⼀个集成了⼀百多个最常⽤linux命令和⼯具的软件,它将许多常⽤的LINUX命令和⼯具结合到了⼀个单独的可执⾏程序中。虽然与相应的GNU⼯具⽐较起来,busybox所提供的功能和参数略少,但在⽐较⼩的系统(例如启动盘)或者嵌⼊式系统中,已经⾜够了。
busybox在设计上就充分考虑了硬件资源受限的特殊⼯作环境。它采⽤⼀种很巧妙的办法减少⾃⼰的体积:所有的命令都通过“插件”的⽅式集中到⼀个可执⾏⽂件中,在实际应⽤过程中通过不同的符号链接来确定到底要执⾏哪个操作。例如最终⽣成的可执⾏⽂件为busybox,当为它建⽴⼀个符号链接ls的时候,就可以通过执⾏这个新命令实现列⽬录的功能。采⽤单⼀执⾏⽂件的⽅式最⼤限度地共享了程序代码,甚⾄连⽂件头、内存中的程序控制块等其他操作系统资源都共享了,对于资源⽐较紧张的系统来说,是最合适不过了。
Busybox配置如下:
Build Options--->
[*] Build BusyBox as a static binary (no shared libs)
Installation Options --->
Login/Password Management Utilities --->
Do you want to build BusyBox with a Cross Compiler。如果要对其他平台进⾏编译就要选择它并设置相应的编译程序前缀。我们选择armv5l-linux-,前⾯加上绝对路径。
Login/Password Management Utilities--->
[*]Use internal password and group functions rather than system functions。这⾥设置使⽤busybox⾃⼰的password和shadow⽂件的功能。
如果需要⼀个交互的登录界⾯,则选择getty、login和passwd
linux配置环境变量jdk编译make TARGET_ARCH=arm,⽣成的⽬标代码位于_install⽬录下。
2. ⽂件系统启动过程
Linux的启动过程主要分成两个阶段:
1.启动内核。在这个阶段,内核装⼊内存并在初始化每个设备驱动器时打印信息。
2.执⾏程序init。装⼊内核并初始化设备后,运⾏init程序。init程序处理所有程序的启动,包括重要系统程序和其它指定在启动时装⼊的软件。textarea去掉边框
现在主要详细介绍⼀下⽂件系统的启动过程,即linux启动过程的第⼆阶段,⼤概分为以下⼏个过程:
(1)运⾏init
init的进程号是1,从这⼀点就能看出,init进程是系统所有进程的起点,linux在完成核内引导以后,就开始运⾏init程序。init程序需要读取配置⽂件/etc/inittab,以查看下⼀步做什么。inittab是⼀个不可执⾏的⽂本⽂件,它有若⼲⾏指令所组成,告诉 init 要进⼊什么运⾏级别,以及在哪⾥可以到该运⾏级别的配置⽂件。以下是qsan的inittab⽂件(部分注释省略):
# The default runlevel.
id:4:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# /etc/init.d executes the S and K scripts upon change of runlevel.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l6:6:wait:/etc/init.d/rc 6
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -h now
# /sbin/getty invocations for the runlevels.
# Example how to put a getty on a serial line (for a terminal)
T0:134:respawn:/sbin/getty -L ttyS0 115200 vt100
T1:1:respawn:/sbin/getty -L ttyS1 115200 vt100
以上⾯的inittab⽂件为例,来说明⼀下inittab的格式。其中以#开始的⾏是注释⾏,除了注释⾏之外,每⼀⾏都有以下格式:id:runlevel:action:process
id – ⼊⼝标识符,⽤于标识⽂件/etc/inittab中的每⼀个登记项。它是⼀个1-4位的字符串,对于getty或mingetty等其他login程序项,要求id与tty的编号相同,否则getty程序将不能正常⼯作。
runlevel – 运⾏级。说明该登记项适⽤于哪⼀个运⾏级。为空表⽰适⽤于所有级别.它是init所处于的运⾏级别标识,⼀般使⽤0-6以及S或s。0、1、6运⾏级别被系统保留。0作为halt动作,1作为重启⾄单⽤户模式,6为重启。S和s意义相同,表⽰单⽤户模式,且⽆需inittab⽂件,因此也不在inittab中出现,实际上,进⼊单⽤户模式时,init直接在控制台(/dev/console)上运⾏/sbin/sulogin。runlevel可以是并列的多个值,以匹配多个运⾏级别,对⼤多数action来说,仅当runlevel与当前运⾏级别匹配成功才会执⾏。
action – 定义init命令应该向进程实施什么动作。包括以下:
respawn-⽆论何时它终⽌,均重新启动命令
wait-运⾏命令⼀次。在继续之前,init等待它终⽌
once-运⾏命令⼀次
boot-命令在启动过程中运⾏。忽略运⾏等级字段
bootwait-命令在启动过程中运⾏,忽略运⾏等级字段。在继续之前,init等待该进程终⽌
initdefault-定义Linux系统的默认运⾏等级
powerwait-停电时命令运⾏。在继续之前,init等待该进程终⽌
powerfail-停电时命令运⾏。在继续之前,init不等待该进程终⽌
powerokwait-恢复电⼒时命令运⾏。在继续之前,init等待该进程终⽌
powerfailnow-UPS发出电池即将耗尽的信号时,运⾏该命令
process - 是具体的执⾏程序。程序后⾯可以带参数。个人网站设计主题
(2)系统初始化item英语怎么读
sysinit、boot、bootwait等action将在系统启动时⽆条件运⾏,⽽忽略其中的runlevel。因此init进程⾸先会执⾏etc/init.d/rcS脚本,rcS内容如下:
#⾸先,定义PATH、runlevel、prevlevel然后导出到环境中
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
#然后,判断是不是第⼀次安装系统,如果是,则检查并且执⾏安装程序留下的脚本
if [ -x /sbin/unconfigured.sh ]
then
/sbin/unconfigured.sh
fi
. /etc/default/rcS
export VERBOSE
#捕捉INT、QUIT、TSTP信号,
trap":"INT QUIT TSTP
#检查/etc/rcS.d/⽬录,看是否有以S开头并且紧跟两个字符(实际上#⼀般是两个数字0-99)命名的⾮普通(! -f"$i")⽂件,如果有则根据#⽂件的类型作出两个选择
# 1,是.sh结尾的脚本时执⾏
# 2,如果不是.sh结尾的脚本,则传递给start参数执⾏这个⽂件
for i in /etc/rcS.d/S??*
do
# Ignore dangling symlinks for now.
[ ! -f"$i"]&& continue
case"$i"in
*.sh)
# Source shell script for speed.
(
trap - INT QUIT TSTP
set start
. $i
)
;;
*)
# No sh extension, so fork subprocess.
$i start
;;
esac
done
#这是为了兼容其他系统的/etc/rc.boot脚本
[ -d /etc/rc.boot ]&& run-parts /etc/rc.boot
#这也是⽤于第⼀次安装系统后需要执⾏的脚本,安装成功后,系统上
#⼀般没有这个脚本
if [ -x /sbin/setup.sh ]
then
/sbin/setup.sh
fi
#/etc/rc.S/rcS脚本执⾏结束.返回/inittab
(3)启动对应运⾏级别的守护进程
返回/inittab,接下来根据系统进⼊的运⾏级别,启动对应运⾏级别的守护进程,这⾥为4,init将执⾏配置⽂件inittab中的以下这⾏:
l4:4:wait:/etc/init.d/rc 4
这⼀⾏表⽰以4为参数运⾏/etc/rc.d/rc,/etc/rc.d/rc是⼀个Shell脚本,它接受4作为参数,去执⾏/etc/rc.d/rc4.d/⽬录下的所有的rc启动脚本,/etc/rc.d/rc4.d/⽬录中的这些启动脚本实际上都是⼀些链接⽂件,⽽不是真正的rc启动脚本,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/⽬录下。⽽这些rc启动脚本有着类似的⽤法,它们⼀般能接受start、stop、restart、status等参数。
/
etc/rc.d/rc4.d/中的rc启动脚本通常是K或S开头的链接⽂件,对于以S开头的启动脚本,将以start参数来运⾏。⽽如果发现存在相应的脚本也存在K打头的链接,⽽且已经处于运⾏态了(以/var/lock/subsys/下的⽂件作为标志),则将⾸先以stop为参数停⽌这些已经启动了的守护进程,然后再重新运⾏。这样做是为了保证是当init改变运⾏级别时,所有相关的守护进程都将重启。
(4)建⽴终端
rc执⾏完毕后,返回init。这时基本系统环境已经设置好了,各种守护进程也已经启动了。init接下来会打开终端,以便⽤户登录系统,如以下2⾏:
T0:134:respawn:/sbin/getty -L ttyS0 115200 vt100
T1:1:respawn:/sbin/getty -L ttyS1 115200 vt100
从上⾯可以看出在1、3、4的运⾏级别中将以respawn⽅式运⾏getty程序,它会显⽰⼀个⽂本登录界⾯,这个界⾯就是我们经常看到的登录界⾯,在这个登录界⾯中会提⽰⽤户输⼊⽤户名,⽽⽤户输⼊的⽤户名将作为参数传给login程序来验证⽤户的⾝份。
linux建立文件系统的命令注意:如果想绕过登录验证过程,想直接进⼊shell界⾯的话,则把以上两⾏注释掉,改为:T0:134:respawn:/bin/sh
(5)登录系统,启动完成
getty进程接收到⽤户名后,启动login进程.
login进程要求⽤户输⼊⼝令.
⽤户输⼊⼝令.
login进程对username和password进⾏检查.
login启动shell进程.
shell进程根据/etc/password中的shell类型,启动相应的shell.并启动/etc/profile⽂件和$HOME/.bash_profile⽂件.最后出现shell 提⽰符,等待⽤户输⼊命令.
⾄此,启动过程结束。
3. login验证过程
Linux的帐号验证程序是login,login会接收getty传来的⽤户名作为⽤户名参数。然后login会对⽤户名进⾏分析:如果⽤户名不是root,且存在/etc/nologin⽂件,login将输出nologin⽂件的内容,然后退出。
这通常⽤来系统维护时防⽌⾮root⽤户登录。只
有/etc/securetty中登记了的终端才允许root⽤户登录,如果不存在这个⽂件,则root可以在任何终端上登录。/etc/usertty⽂件⽤于对⽤户作出附加访问限制,如果不存在这个⽂件,则没有其他限制。
在分析完⽤户名后,login将搜索/etc/passwd以及/etc/shadow来验证密码以及设置帐户的其它信息,⽐如:主⽬录是什么、使⽤何种shell。如果没有指定主⽬录,将默认为根⽬录;如果没有指定shell,将默认为/bin/bash。
login程序成功后,会向对应的终端在输出最近⼀次登录的信息(在/var/log/lastlog中有记录),并检查⽤户是否有新邮件
(在/usr/spool/mail/的对应⽤户名⽬录下)。然后开始设置各种环境变量:对于bash来说,系统⾸先寻/etc/profile脚本⽂件,并执⾏它;然后如果⽤户的主⽬录中存在.bash_profile⽂件,就执⾏它,在这些⽂件中⼜可能调⽤了其它配置⽂件,所有的配置⽂件执⾏后,各种环境变量也设好了,这时会出现⼤家熟悉的命令⾏提⽰符,到此整个启动过程就结束了。
以下是passwd,shadow和group脚本的格式说明:
/etc/passwd密码⽂件的格式如下所⽰:
⽤户名:⼝令:⽤户标识号:组标识号:注释性描述:主⽬录:登录Shell
user_name:password:uid:gid:comment:home:shell
每⾏有很多项组成,项与项之间⽤":"隔开.每项的说明如下:
user_name ⽤户名
password 登录密码,初始设置时为空
uid ⽤户识别号(User ID),是⼀数值,每个⽤户的识别号不同
gid ⽤户组识别号,参见/etc/group⽂件
comment 注释,可以任意字符,⼀般⽤来说明⽤户的⾝份特征
home 家⽬录名
shell 该⽤户缺省shell,⼀般取值为:/bin/sh,/bin/ksh,/bin/csh
/etc/shadow⽂件格式如下:
登录名:加密⼝令:最后⼀次修改时间:最⼩时间间隔:最⼤时间间隔:警告时间:不活动时间:失效时间:标志
pdb数据库是什么数据库username:passwd:last:may:must:warn:expire:disable:reserved
username 使⽤者名称
passwd 编码密码
last 密码上次更动⽇期,以从1970年1⽉1⽇算起的天数代表
may 密码改变前天数
must 密码最常使⽤天数
warn 代表期限前⼏天就事先警告使⽤者
expire 超过密码过期天数后,就关闭该帐号
disable 帐号关闭,以从1970年1⽉1⽇算起的天数代表
reserved 预备栏位
/etc/group⽂件格式如下:
group_name:password:gid:members_list
每⾏有四项组成,项与项之间⽤":"隔开.
group_name ⽤户组名
password ⽤户组密码,⼀般为空
gid ⽤户组识别号(Group ID),是⼀数值,每个组的识别号不同
members_list 该组成员列表,由⼀个或多个⽤户名组成,⽤户名之间⽤逗号隔开
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论