ITEEDU

Linux系统学习基础

第一章 开发工具学习

第二章 Linux内核制作

第三章 initramfs制作

第四章 Linux系统制作原理

第五章 文件系统启动方式配制

sysinit文件写法详解

sysinit文件是linux初始化文件系统时执行的第一个脚本文件。它主要做在各个运行级别中进行初始化工作,包括: 启动交换分区;检查磁盘;设置主机名;检查并挂载文件系统;加载并初始化硬件模块.

具体执行的脚本由inittab文件中的action为sysinit的一行确定。如LFS中为如下一行:

si::sysinit:/etc/rc.d/init.d/rc sysinit

这代表init初始化程序执行的第一个脚本为/etc/rc.d/init.d/rc,并传入sysinit参数。一般linux传入的参数为一数字,代表运行级别。rc会用参数合成/etc/init.d/rcsysinit.d目录,并执行其中的文件完成服务初始化。下面是/etc/init.d/rcsysinit.d目录中的文件。

│   └── rcsysinit.d
│       ├── S00mountkernfs -> ../init.d/mountkernfs
│       ├── S02consolelog -> ../init.d/consolelog
│       ├── S05modules -> ../init.d/modules
│       ├── S10udev -> ../init.d/udev
│       ├── S20swap -> ../init.d/swap
│       ├── S30checkfs -> ../init.d/checkfs
│       ├── S40mountfs -> ../init.d/mountfs
│       ├── S45cleanfs -> ../init.d/cleanfs
│       ├── S50udev_retry -> ../init.d/udev_retry
│       ├── S70console -> ../init.d/console
│       ├── S80localnet -> ../init.d/localnet
│       └── S90sysctl -> ../init.d/sysctl

下面我们来看一下LFS中rc文件的写法。

#!/bin/sh
#------------------------------------
#sysconfig/rc只定义了几个变量,内容如下:
#rc_base=/etc/rc.d
#rc_functions=${rc_base}/init.d/functions
#network_devices=/etc/sysconfig/network-devices
#----------------------------------------------
. /etc/sysconfig/rc
#由上面知rc_function为 "/etc/rc.d/init.d/functions"
#文件只设置了一变量,如PATH="/bin:/usr/bin:/sbin:/usr/sbin".还有一些函数
. ${rc_functions}

# This sets a few default terminal options.
stty sane

# These 3 signals will not cause our script to exit
trap "" INT QUIT TSTP
#如果 ${1}不为空,runlevel 为 ${1}。${1}是脚本的第一个参数
[ "${1}" != "" ] && runlevel=${1}

#如果runlevel为空则退出.${0}为脚本名字
if [ "${runlevel}" = "" ]; then
	echo "Usage: ${0} " >&2
	exit 1
fi
#当运行级变化时,PREVLEVEL存储当前runlevel变量.
previous=${PREVLEVEL}
#if previous is null, previous is setted N.
#when boot system,the previous is null.
[ "${previous}" = "" ] && previous=N
#对应runlevel的目录不存在则退出。
#boot_mesg为一个向屏幕输出字符串的函数
if [ ! -d ${rc_base}/rc${runlevel}.d ]; then
	boot_mesg "${rc_base}/rc${runlevel}.d does not exist." ${WARNING}
	boot_mesg_flush
	exit 1
fi

# 停止前一个运行级的所有服务,退出这一runlevel
# 当启动系统时,下面不会运行。不必细看
if [ "${previous}" != "N" ]; then
	for i in $(ls -v ${rc_base}/rc${runlevel}.d/K* 2> /dev/null)
	do
		check_script_status

		suffix=${i#$rc_base/rc$runlevel.d/K[0-9][0-9]}
		prev_start=$rc_base/rc$previous.d/S[0-9][0-9]$suffix
		sysinit_start=$rc_base/rcsysinit.d/S[0-9][0-9]$suffix

		if [ "${runlevel}" != "0" ] && [ "${runlevel}" != "6" ]; then
			if [ ! -f ${prev_start} ] && [ ! -f ${sysinit_start} ]; then
				boot_mesg -n "WARNING:\n\n${i} can't be" ${WARNING}
				boot_mesg -n " executed because it was not"
				boot_mesg -n " not started in the previous"
				boot_mesg -n " runlevel (${previous})."
				boot_mesg "" ${NORMAL}
				boot_mesg_flush
				continue
			fi
		fi
		${i} stop
		error_value=${?}

		if [ "${error_value}" != "0" ]; then
			print_error_msg
		fi
	done
fi

#开启当前runlevel的所有服务,主要是这一段要明白。
for i in $( ls -v ${rc_base}/rc${runlevel}.d/S* 2> /dev/null)
do

	if [ "${previous}" != "N" ]; then #this if is false when booting.
		suffix=${i#$rc_base/rc$runlevel.d/S[0-9][0-9]}
		stop=$rc_base/rc$runlevel.d/K[0-9][0-9]$suffix
		prev_start=$rc_base/rc$previous.d/S[0-9][0-9]$suffix

		[ -f ${prev_start} ] && [ ! -f ${stop} ] && continue
	fi

	check_script_status #a function judgeing the file if is a file and executable. 

	case ${runlevel} in
		0|6) #if runleve is 0 or 6, stop the service i.
			${i} stop
			;;
		*)
			${i} start
			;;
	esac
	error_value=${?}

	if [ "${error_value}" != "0" ]; then
		print_error_msg
	fi
done

# End $rc_base/init.d/rc