arago rootfs的sysvinit启动流程

2680阅读 0评论2016-01-24 edaplayer
分类:嵌入式

内核会查找init进程,有默认几个init路径,最后发现/sbin/init存在,于是执行/sbin/init,这个init实际上是init.sysvinit的软链接

init.sysvinit读取/etc/inittab

# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $

# The default runlevel.
id:5:initdefault:

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS

# What to do in single-user mode.
~~:S:wait:/sbin/sulogin

# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

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
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
O0:12345:respawn:/sbin/getty -L 115200 ttyO0
# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
#  :::
#

1:12345:respawn:/sbin/getty 38400 tty1


根据LFS中的介绍,现在运行级别为5,我们就认为是正常运行的级别就行了。
0: 关闭计算机
1: 单用户模式
2: 无网络多用户模式
3: 有网络多用户模式
4: 保留作自定义,否则同运行级 3 
5: 同运行级 4,一般用于图形界面(GUI)登录(如 X的 xdm 或 KDE的 kdm
6: 重启动计算机
开机执行了5个程序/脚本:
/etc/init.d/rcS                /**/
~~:S:wait:/sbin/sulogin  /**/
/etc/init.d/rc 5
O0:12345:respawn:/sbin/getty -L 115200 ttyO0
/sbin/getty 38400 tty1

sulogin需要输入用户名和密码,如果想改成自动登录可参考:
http://blog.csdn.net/swliao/article/details/5989203

/etc/init.d/rcS将运行级别提升到S级别,设置PATH并且导入 /etc/default/rcS 中的环境变量(初始化runlevel=S和prevlevel=N
),执行trap ":" INT QUIT TSTP,使得Ctrl+C不会退出当前控制台,只会退出子shell。,最后一步是执行exec /etc/init.d/rc S
(注意inittab里后面还会执行一次/etc/init.d/rc 5

/etc/init.d/rcS内容:

PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022 /*设置对文件默认的操作权限,比如新建一个文件时*/
export PATH runlevel prevlevel


# Make sure proc is mounted
#
[ -d "/proc/1" ] || mount /proc


#
# Source defaults.
#
. /etc/default/rcS


#
# Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP


#
# Call all parts in order.
#
exec /etc/init.d/rc S

重点来了,/etc/init.d/rc 根据运行级别,使用for循环启动/etc/rcX.d中的所有链接的脚本(服务),按序号可以从 00 到 99(数字越小执行的越早)。

因此,关机的时候运行级别是0,自然是执行rc0.d目录下的脚本。

那么为什么先执行/etc/init.d/rc S,然后执行/etc/init.d/rc 5呢? 目前猜测是因为先执行/etc/init.d/rc S,初始化一些变量,后面执行/etc/init.d/rc 5时可以根据变量值显示启动进度。

最后补充一下logo和进度条的实现:
logo和进度条的启动服务是rcS.d/S00psplash.sh实现的,实际上是init.d/pspsplash.sh
#!/bin/sh 
### BEGIN INIT INFO
# Provides:             psplash
# Required-Start:
# Required-Stop:
# Default-Start:        S
# Default-Stop:
### END INIT INFO


read CMDLINE < /proc/cmdline
for x in $CMDLINE; do
        case $x in
        psplash=false)
echo "Boot splashscreen disabled" 
exit 0;
                ;;
        esac
done


export TMPDIR=/mnt/.psplash
mount tmpfs -t tmpfs $TMPDIR -o,size=40k


rotation=0
if [ -e /etc/rotation ]; then
read rotation < /etc/rotation
fi


/usr/bin/psplash --angle $rotation &

psplash服务启动后,在rcS里就会根据已启动的进程计数,输出进度条。
开机进度条:
    if [ -e /mnt/.psplash/psplash_fifo ]; then
        echo "PROGRESS $progress" > /mnt/.psplash/psplash_fifo
    fi

开机背景logo:
if [ "x$runlevel" != "xS" ] && [ ! -x /etc/rc${runlevel}.d/S??xserver-nodm ]; then
    if type psplash-write >/dev/null 2>&1; then
        TMPDIR=/mnt/.psplash psplash-write "QUIT" || true
    umount· -l /mnt/.psplash
    fi
fi

type命令用于判断命令是否是内部命令,其实这里是判断logo程序是否存在。

上一篇:ini解析库
下一篇:s5pv210 USB启动模式下的内存映射