Linux文件系统启动过程及login的实现 .

来源:互联网 发布:便携工具 知乎 编辑:程序博客网 时间:2024/05/01 10:35

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

 

编译make TARGET_ARCH=arm,生成的目标代码位于_install目录下。

2. 文件系统启动过程

Linux的启动过程主要分成两个阶段:

   1.启动内核。在这个阶段,内核装入内存并在初始化每个设备驱动器时打印信息。
   2.执行程序init。装入内核并初始化设备后,运行init程序。init程序处理所有程序的启动,包括重要系统程序和其它指定在启动时装入的软件。

现在主要详细介绍一下文件系统的启动过程,即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

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)系统初始化

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程序来验证用户的身份。

注意:如果想绕过登录验证过程,想直接进入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文件格式如下:

登录名:加密口令:最后一次修改时间:最小时间间隔:最大时间间隔:警告时间:不活动时间:失效时间:标志

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 该组成员列表,由一个或多个用户名组成,用户名之间用逗号隔开

 

注:一个最简单的文件系统至少需要包含以下几个目录,/sbin,/bin,/dev(需要console和ttyS0两个文件),/proc,/etc(需要inittab,rcS文件),/home.

 

嵌入式linux用户密码验证

开发板启动内核后,一般是直接按回车键就能直接进入文件系统,以前一直搞不懂为什么不需要用户密码 
验证,今天上网查看了一下,原来是因为配置文件的问题。
    原来一直以为用户密码验证是由运用程序做的,后来,上网查了一下,原来是由文件系统完成的,
在编译busybox的时候把相关的选项选上,就可以支持用户密码登录了,见下图。
Linux文件系统启动过程及login的实现 - sunnyshineboy - sunnyshineboy的博客
    编译好busybox之后,在可执行文件中,可以找一个文件名为login的软链接,就是负责用户验证登录的。
    可以直接拷贝主机的passwd 和 shadow 两个文件到开发板的/etc目录下.
    在/etc/init.d/rcS文件中加入 
    /bin/login
    重启开发板,登录就需要密码验证了
    
    还可以在/etc创建一个inittab文件,
    添加
    ::respawn:-/bin/login
    ::sysinit:/etc/init.d/rcS
   

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机nfc功能被手机壳挡住怎么办 飞信短信登录验证码达到上限怎么办 手机自带短信软件没了怎么办 老婆出轨孩子又3个不知道怎么办 骑电动车摔跤小脚趾疼有点肿怎么办 第一次太疼了有心理阴影了怎么办 天梭机械表调了时间忽然慢怎么办 支付宝信用住到酒店没房间怎么办 拳头打在硬上骨头肿了怎么办 领导决策出现了失误你该怎么办 我的直销团队走到瓶颈了怎么办 孕妇8个月便秘大便带血怎么办 爱他美金装冲泡有泡沫怎么办 做雅思听力时理解不了原文怎么办 英国读语言班不想读研了怎么办 英国读研本科学位不够分怎么办 英国华威大学读研没分到宿舍怎么办 英国留学申请大学成绩没通过怎么办 很想上专升本但是专科挂科怎么办 英国学校申请的gpa太低了怎么办 博士面试通过后导师不签名怎么办 资助出国留学协议书写错了怎么办 人生最低谷运气最差的时候怎么办 孩子出国留学一年后想回国怎么办 领导给我娃的钱我怎么办 在西浦大三成绩不好影响申研怎么办 日本国想在中国开分公司要怎么办 美国生完孩子做飞机婴儿怎么办 会计专硕复试英语面试不好怎么办 被打过狂犬疫苗的狗咬了怎么办 保姆和雇主带孩子玩受伤了怎么办 银行流水造假拒签10年怎么办 老师进修被学校扣工资该怎么办 老婆性格太倔结婚一年想离婚怎么办 天正打图窗户线条太粗怎么办 孩子在幼儿园不敢跟老师说话怎么办 温州教育准考证号密码忘了怎么办 高等继续教育网打不开课程怎么办 安运继续教育的登录密码忘了怎么办 金蝶k3账套管理打不开了怎么办 仁和会计课堂app不能用怎么办