linux学习之系统启动过程
1.内核引导
操作系统接管硬件之后,首先读入/boot目录下的内核文件,本人使用ubuntu 15.10
:
2.启动初始化进程
没有这个进程,系统中任何进程都不会启动,从进程编号(pid)看出,init
是第一个运行的程序:
ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 185192 5788 ? Ss 3月03 0:10 /sbin/init splash
//各栏位意义,参考鸟哥私房菜
USER:该 process 属於哪个使用者帐号的?
PID :该 process 的程序识别码。
%CPU:该 process 使用掉的 CPU 资源百分比;
%MEM:该 process 所占用的实体内存百分比;
VSZ :该 process 使用掉的虚拟内存量 (Kbytes)
RSS :该 process 占用的固定的内存量 (Kbytes)
TTY :该 process 是在那个终端机上面运行,若与终端机无关则显示 ?,另外, tty1-tty6是本机上面的登陆者程序,若为 pts/0 等等的,则表示为由网络连接进主机的程序。
STAT:该程序目前的状态,状态显示与 ps -l 的 S 旗标相同 (R/S/T/Z)
START:该 process 被触发启动的时间;
TIME :该 process 实际使用 CPU 运行的时间。
COMMAND:该程序的实际命令为何?
所以第一个运行的程序是/sbin/init
。
3.运行级别
Linux中许多程序需要开机启动,称之为daemon(守护进程)
,init
的进程的一大任务就是去运行这些开机启动的程序;那么linux怎么确定启动哪些程序呢?这就涉及到运行级别(runlevel)
,不同的运行级别启动不同的程序。
Linux系统有7个运行级别:
0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动
1:单用户工作状态,root权限,用于系统维护,禁止远程登陆
2:多用户状态(没有NFS)
3:完全的多用户状态(有NFS),登陆后进入控制台命令行模式
4:系统未使用,保留
5:X11控制台,登陆后进入图形GUI模式
6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动
启动了init
进程之后,其首先会读取/etc/inittab
文件来进行初始化工作,就是查看运行级别,然后确定要启动的程序。
但这里要注意一个问题,现在的linux发行版本,主要有以下初始化方式,分别是sysvinit (System V initialization)
、ubuntu的Upstart
以及systemd
,所以在ubuntu
环境下,改用/etc/init/rc-sysinit.conf
,以前的版本有可能是在/etc/event.d
中。
所以在初始化的时候会读取rc-sysinit.conf
并执行相关配置和脚本,其主要作用是设置系统默认runlevel(运行级别)
。
下面是rc-sysinit.conf的代码:
# rc-sysinit - System V initialisation compatibility
#
# This task runs the old System V-style system initialisation scripts,
# and enters the default runlevel when finished.
description "System V initialisation compatibility"
author "Scott James Remnant <scott@netsplit.com>"
start on (filesystem and static-network-up) or failsafe-boot
stop on runlevel
# Default runlevel, this may be overriden on the kernel command-line
# or by faking an old /etc/inittab entry
env DEFAULT_RUNLEVEL=2 #默认运行级别为2
emits runlevel
# There can be no previous runlevel here, but there might be old
# information in /var/run/utmp that we pick up, and we don't want
# that.
#
# These override that
env RUNLEVEL=
env PREVLEVEL=
console output
env INIT_VERBOSE
task
script
# Check for default runlevel in /etc/inittab
if [ -r /etc/inittab ]
then
eval "$(sed -nre 's/^[^#][^:]*:([0-6sS]):initdefault:.*/DEFAULT_RUNLEVEL="\1";/p' /etc/inittab || true)"
fi
# Check kernel command-line for typical arguments
for ARG in $(cat /proc/cmdline)
do
case "${ARG}" in
-b|emergency)
# Emergency shell
[ -n "${FROM_SINGLE_USER_MODE}" ] || sulogin
;;
[0123456sS])
# Override runlevel
DEFAULT_RUNLEVEL="${ARG}"
;;
-s|single)
# Single user mode
[ -n "${FROM_SINGLE_USER_MODE}" ] || DEFAULT_RUNLEVEL=S
;;
esac
done
# Run the system initialisation scripts
[ -n "${FROM_SINGLE_USER_MODE}" ] || /etc/init.d/rcS
# Switch into the default runlevel
telinit "${DEFAULT_RUNLEVEL}" #调用telinit进入设置的runlevel
end script```
通过代码可以看出其会检测是否存在/etc/inittab,说明该系统下也支持`sysvinit (System V initialization)`初始化方式,然后其设定的默认运行级别是2。
终端输入命令`runlevel`会返回当前运行级别,本机返回`N 2`;再看倒数第二行,`telinit "${DEFAULT_RUNLEVEL}" `调用了telinit进入了设定的runlevel。
再来看看当前目录下的rc.conf文件:
``` shell
# rc - System V runlevel compatibility
#
# This task runs the old System V-style rc script when changing between
# runlevels.
description "System V runlevel compatibility"
author "Scott James Remnant <scott@netsplit.com>"
emits deconfiguring-networking
emits unmounted-remote-filesystems
start on runlevel [0123456]
stop on runlevel [!$RUNLEVEL]#这里$RUNLEVEL=2,表示非2就不启动
export RUNLEVEL
export PREVLEVEL
console output
env INIT_VERBOSE
task
script
if [ "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" -o "$RUNLEVEL" = "6" ]; then
status plymouth-shutdown 2>/dev/null >/dev/null && start wait-for-state WAITER=rc WAIT_FOR=plymouth-shutdown || :
fi
/etc/init.d/rc $RUNLEVEL
end script
由代码/etc/init.d/rc $RUNLEVEL
可看出/etc/init.d/rc
接受参数$RUNLEVEL
来调用/etc/rc${runlevel}.d/
下的脚本,这里以/etc/rc2.d
为例,列出该目录下的文件:
ls -l /etc/rc2.d
总用量 4
-rw-r--r-- 1 root root 677 6月 15 2015 README
lrwxrwxrwx 1 root root 21 3月 23 21:03 S05loadcpufreq -> ../init.d/loadcpufreq
lrwxrwxrwx 1 root root 17 3月 23 21:03 S16openvpn -> ../init.d/openvpn
lrwxrwxrwx 1 root root 22 3月 23 21:03 S19cpufrequtils -> ../init.d/cpufrequtils
lrwxrwxrwx 1 root root 17 3月 23 21:03 S20hddtemp -> ../init.d/hddtemp
lrwxrwxrwx 1 root root 20 3月 23 21:03 S20kerneloops -> ../init.d/kerneloops
lrwxrwxrwx 1 root root 20 3月 23 21:03 S20mintsystem -> ../init.d/mintsystem
lrwxrwxrwx 1 root root 15 3月 23 21:03 S20rsync -> ../init.d/rsync
lrwxrwxrwx 1 root root 27 3月 23 21:03 S20speech-dispatcher -> ../init.d/speech-dispatcher
lrwxrwxrwx 1 root root 32 3月 23 21:03 S20virtualbox-guest-utils -> ../init.d/virtualbox-guest-utils
lrwxrwxrwx 1 root root 15 3月 23 21:03 S50saned -> ../init.d/saned
lrwxrwxrwx 1 root root 19 3月 23 21:03 S70dns-clean -> ../init.d/dns-clean
lrwxrwxrwx 1 root root 18 3月 23 21:03 S70pppd-dns -> ../init.d/pppd-dns
lrwxrwxrwx 1 root root 17 3月 25 22:51 S91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 21 3月 23 21:03 S99grub-common -> ../init.d/grub-common
lrwxrwxrwx 1 root root 18 3月 23 21:03 S99ondemand -> ../init.d/ondemand
lrwxrwxrwx 1 root root 19 3月 24 00:03 S99prltoolsd -> ../init.d/prltoolsd
lrwxrwxrwx 1 root root 18 3月 23 21:03 S99rc.local -> ../init.d/rc.local
该目录下的文件名的命名形式都是字母S+两位数字+程序名
,S表示start,如果是K,就表示kill,两位数字表示处理顺序,越小越早处理,如果数字相同,就按照字母顺序进行启动。
从中还可以看出这些文件的真正目录都在/etc/init.d
目录下,这是为了防止在不同的运行级别下启动相同的程序,这样设置为链接提供了很大的方便。
后面执行login程序进行登录。
暂时over,以后对代码进行更加详细的说明。