美文网首页DEVOPS我用 Linux程序员
linux学习之系统启动过程

linux学习之系统启动过程

作者: howie6879 | 来源:发表于2016-03-28 14:34 被阅读405次

    1.内核引导

    操作系统接管硬件之后,首先读入/boot目录下的内核文件,本人使用ubuntu 15.10:

    boot.png

    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,以后对代码进行更加详细的说明。

    相关文章

      网友评论

      本文标题:linux学习之系统启动过程

      本文链接:https://www.haomeiwen.com/subject/feftlttx.html