• centos5,6 系统启动流程


    linux内核特点:

    • 支持模块化:模块文件的名字以.ko(kernel object)结尾
    • 支持内核运行时,动态加载和卸载模块文件。

    linux内核组成部分:

    • 核心文件:/boot/vmlinuz-VERSION-release

      # ll /boot/vmlinuz-3.10.0-957.el7.x86_64
      -rwxr-xr-x. 1 root root 6639904 Nov  9  2018 /boot/vmlinuz-3.10.0-957.el7.x86_64
      # file /boot/vmlinuz-3.10.0-957.el7.x86_64
      /boot/vmlinuz-3.10.0-957.el7.x86_64: Linux kernel x86 boot executable bzImage, version 3.10.0-957.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) #1 S, RO-rootFS, swap_dev 0x6, Normal VGA
      
    • 模块文件:/lib/modules/VERSION-release

      如果按照了多个内核版本,则/lib/modules下,有多个目录

      # ll /lib/modules
      drwxr-xr-x. 8 root root 4096 Feb 20 10:03 3.10.0-957.el7.x86_64
      

      3.10.0-957.el7.x86_64目录下的文件:

      # ls /lib/modules/3.10.0-957.el7.x86_64/
      build   modules.alias      modules.builtin.bin  modules.drm          modules.softdep      updates
      extra   modules.alias.bin  modules.dep          modules.modesetting  modules.symbols      vdso
      kernel  modules.block      modules.dep.bin      modules.networking   modules.symbols.bin  weak-updates
      misc    modules.builtin    modules.devname      modules.order        source
      

      其中有:kernel目录

      # ls /lib/modules/3.10.0-957.el7.x86_64/kernel/
      arch  crypto  drivers  fs  kernel  lib  mm  net  sound  virt
      

      arch:平台特有;crypto:加密/解密;drivers:驱动管理;mm:内存管理。fs:文件系统;net:网络管理;sound:声卡驱动

    • ramdisk:

      ramdisk的由来:操作系统不知道用户的电脑上的磁盘设备是什么型号的,访问特定磁盘是要使用特定的磁盘驱动程序的,所以操作系统可能就要把市面上主流的磁盘驱动程序都准备好,放入安装盘中,这样一来安装盘太臃肿。为了解决这个问题,操作系统不准备任何磁盘驱动程序,而是在安装操作系统的过程中,扫描用户的硬件,根据硬件自动生成磁盘驱动程序,并把这个驱动程序存放入磁盘中。

      开机后,内核被装载到内存后,就要去从磁盘找根文件系统。内核要想访问磁盘,必须需要访问磁盘的驱动程序,可是磁盘的驱动程序又在根文件系统里,所以内核就无法找到磁盘的驱动程序,也就无法访问磁盘。所以需要一个临时的根文件系统,在里面放磁盘的驱动程序。这个临时的驱动程序和根文件系统,是在安装操作系统时,由安装程序扫描机器的硬件后,根据硬件的型号自动生成的。有了这个东西后,内核就先把一段内存模拟成磁盘,把这个东西放到内存中,从它的里面取得到磁盘驱动,然后使用好不容易得到的驱动程序,去访问真的磁盘,得到真的根文件系统。然后真的根文件系统,取代这个东西。

      这个东西叫:ramdisk。

      我们使用free命令,可以看到buff和cache。为什么有buff和cache呢?因为磁盘IO太慢,所以把经常访问的磁盘上的数据,载入内存的buff和cache区域。

      # free
                    total        used        free      shared  buff/cache   available
      Mem:        3880164      459420     2525300       12596      895444     3076684
      Swap:       4063228           0     4063228
      

      centos5:/boot/initrd-VERSION-release.img

      由于是用内存模拟磁盘,所以内存又使用buff和cache机制,缓存了磁盘的内容,造成了双重buff和cache。

      centos6,7:/boot/initramfsVERSION-release.img

      为了防止双重buffer和cache,centos6和7使用ramfs,ramfs是文件系统,就防止了双重buff和cache。

      # ll /boot/initramfs-3.10.0-957.el7.x86_64.img
      -rw-------. 1 root root 31489644 Nov 29 17:11 /boot/initramfs-3.10.0-957.el7.x86_64.img
      

      ramdisk的做成工具程序:

      • centos5:mkinitrd
      • centos6,7:dracut。为了兼容centos5,也可以使用mkinitrd

    centos5系统启动流程

    前提pc主机,MBR架构

    • 第一步:post(power on system test)加电自检。

      pc机的主板上有个rom芯片(CMOS),加电后,cpu去找这个raw,然后读取里面的指令,检测机器上是否有:内存,硬盘,显示设备等。

      CMOS里有个bios(basic input output system)程序

    • 第二步:boot sequence(bios里设置是用光盘启动,还是硬盘启动等)

      按次序查找引导设备,第一个有引导程序(bootloader)的设备即为本次启动要用到的设备。

      bootloader:

      • 功能:

        • 找到磁盘上的grub程序,并加载运行之。
        • grub提供一个可以让用户选择的菜单,上面写着,可以选择运行的内核列表
        • 把用户选定的内核程序从磁盘加载到内存的特定空间中,然后解压,展开,此后,内核就开始真正运行起来了,然后bootloader退出,由内核接管一切。

        注意:由于bootloader仅有446字节,它无法读取LVM,软RAID的逻辑分区,只能读取物理分区,所以内核程序只能存放在物理分区上。

      • 种类:

        • LILO:linux loader。它有个致命弱点,如果内核在磁盘的1024以后的柱面上存储着的话,它无法加载内核。安卓手机用的是LILO。

        • GRUB:Grand Uniform Bootloader

          centos5,6用的版本是:grub 0.x(别名:grub legacy)

          cengtos7用的版本是:grub 1.x(别名:grub2)

      bootloader程序放在哪里了?

      如果是MBR架构,则放在了在0号track(磁道),0号sector(扇区)里 的前446bytes 。

      由于只有446字节,空间太小了,能写的程序实在有限,所以linux使用GRUB机制。

      GRUB机制:不让bootloader直接加载内核,而是让bootloader加载磁盘上的另外一个程序/boot/grub。由于/boot/grub是放在磁盘上的,所以突破了446字节的约束。

      • 第一阶段:bootloader加载/boot/grub程序
      • 第1.5阶段:filesystem driver?
      • 第二阶段:/boot/grub程序加载内核。
    • 第三步:kernel自身初始化

      • 探测所以硬件设备

      • 为了加载磁盘上的根文件系统,所以先加载ramdisk上的文件系统,找到里面的磁盘驱动程序。

        注意:也有可能不使用ramdisk。当自己在自己的机器上编译内核时,编译程序就探测到了本地磁盘类型,所以在编译的时候,就可以把磁盘的驱动,编译到内核里,所以内核就不需要再去找ramdisk了。

      • 使用磁盘驱动,以只读方式,加载根文件系统。只读的目的:防止内核有bug,把根文件系统里面的东西删除了。没问题后,再改为读写方式。

      • 运行用户空间的第一个应用程序:/sbin/init

        centos5之前的init程序:SysV init

        ​ 使用的配置文件:/etc/inittab

        centos6的init程序:Upstart

        ​ 使用的配置文件:/etc/init/*.conf

        centos7的init程序:Systemd

        ​ 使用的配置文件: /usr/lib/systemd/system目录下的文件,和/etc/systemd/system目录下的文件

    • 第四步:/sbin/init会启动/sbin/mingetty程序,显示可以登录的文本界面。

    Linux的运行级别

    为了系统的维护等目的设定了7个级别(0~6)

    • 级别0:关机 shutdown
    • 级别1:单用户模式(single user),以root用户登录,无需输入root密码。root密码忘记了,使用级别1。输入维护模式。
    • 级别2:多用户模式(multi user),会启动网络功能,但不会启动NFS。属于维护模式。
    • 级别3:多用户模式(multi user),完全功能模式,但不启动图形界面。
    • 级别4:预留级别,没有被使用,但习惯以同3级别功能使用。
    • 级别5:多用户模式(multi user),完全功能模式,开机自动启动图形界面。
    • 级别6:重启 reboot

    默认级别是3或5,server用级别3;个人主机用级别5.

    切换级别的命令:init 级别

    查看当前的级别:who -r或者runlevel

    run命令的结果里的N:上一次的级别。由于没切换过级别,所以上一次就是N。

    # who -r
    run-level 5  2020-02-20 10:03
    # runlevel
    N 5
    

    init程序的配置文件说明

    1,centos5,6:/etc/inittab

    每行定义一种action,以及与之对应的process

    每一行的格式:id:runlevel:action:process

    id:标识

    runlevel:运行级别

    action:指明启动process的条件

    • wait:当运行级别切换至此行的级别时,执行一次process
    • respawn:一旦此行的process终止,就自动重新启动它
    • initdefault:设定系统开机时默认的运行级别,所以此行的process省略
    • sysinit:设定系统初始化的方式,所以runlevel省略,process一般为/etc/rc.d/rc.sysinit脚本

    process:程序

    例子:

    • id01:3:initdefault:

      系统开机时,以级别3运行。

    • id02::sysinit:/etc/rc.d/rc.sysinit

      不管以哪个级别运行,都使用/etc/rc.d/rc.sysinit脚本完成系统初始化。

    • id03:3:wait:/etc/rc.d/rc 0

      当切换到级别3后,运行脚本:/etc/rc.d/rc 0一次。

    脚本/etc/rc.d/rc的作用:当切换运行级别时,定义先kill哪些进程,然后再启动哪些进程。

    • 脚本参数:运行级别

    解释脚本/etc/rc.d/rc之前,先看看目录/etc/rc.d/下的构成。

    下面有rc0.d,rc1.d,rc2.d,rc3.d,rc4.d,rc5.d,rc6.d目录

    # ll /etc/rc.d/
    drwxr-xr-x. 2 root root  4096 Feb 21 09:19 init.d
    -rwxr-xr-x. 1 root root  2617 Jun 19  2018 rc
    drwxr-xr-x. 2 root root  4096 Feb 21 09:19 rc0.d
    drwxr-xr-x. 2 root root  4096 Feb 21 09:19 rc1.d
    drwxr-xr-x. 2 root root  4096 Feb 21 09:19 rc2.d
    drwxr-xr-x. 2 root root  4096 Feb 21 09:19 rc3.d
    drwxr-xr-x. 2 root root  4096 Feb 21 09:19 rc4.d
    drwxr-xr-x. 2 root root  4096 Feb 21 09:19 rc5.d
    drwxr-xr-x. 2 root root  4096 Feb 21 09:19 rc6.d
    -rwxr-xr-x. 1 root root   220 Jun 19  2018 rc.local
    -rwxr-xr-x. 1 root root 20199 Jun 19  2018 rc.sysinit
    
    

    /etc/rc.d/rc的脚本内容摘要:

    变量$runlevel,就是执行此脚本时,传进来的参数,也就是运行级别。

    # First, run the KILL scripts.
    for i in /etc/rc$runlevel.d/K* ; do
    #省略
    	$i stop
    #省略
    done
    # Now run the START scripts.
    for i in /etc/rc$runlevel.d/S* ; do
    #省略
       $i start
    #省略
    done
    

    所以当运行/etc/rc.d/rc 3的时候,实际运行的脚本的就/etc/rc3.d/目录下的:K*和S*的所有脚本。

    查看一下ls /etc/rc.d/rc3.d的目录,发现都是符号链接文件,指向的是/etc/init.d目录下的相应的脚本。其他的rc1.d等目录下也都是符号链接,而且指向的也是/etc/init.d目录下的相应的脚本。所有不管传的运行级别参数是什么,实际运行的脚本都是/etc/init.d下的相应的脚本。

    # ll /etc/rc.d/rc3.d/K*
    lrwxrwxrwx. 1 root root 15 Jan 31 14:09 /etc/rc.d/rc3.d/K01numad -> ../init.d/numad
    lrwxrwxrwx. 1 root root 16 Jan 31 14:09 /etc/rc.d/rc3.d/K01smartd -> ../init.d/smartd
    # ll /etc/rc.d/rc3.d/S*
    lrwxrwxrwx. 1 root root 17 Jan 31 14:09 /etc/rc.d/rc3.d/S01sysstat -> ../init.d/sysstat
    lrwxrwxrwx. 1 root root 22 Jan 31 14:09 /etc/rc.d/rc3.d/S02lvm2-monitor -> ../init.d/lvm2-monitor
    lrwxrwxrwx. 1 root root 14 Jan 31 14:09 /etc/rc.d/rc3.d/S05rdma -> ../init.d/rdma
    

    那么,为什么弄出这么多符号链接呢?

    观察这些符号链接,发现:K和S的后面都有2位数字。

    这2位数字是为了排序用的,/etc/rc.d/rc脚本的for i in /etc/rc$runlevel.d/K* ; do语句,就把以K后S开头的按后面的数字排序了。

    • K##:要被结束的进程。##数字越小,先被结束。所以不被别的进程依赖的进程,数字小。
    • S##:要被启动的进程。##数字越小,先被启动。所以被别的进程依赖的进程,数字小。

    启动服务时,都是使用service 服务程序名 start,其实service命令,调用的是就是/etc/init.d目录下的脚本,所以直接运行脚本和使用service命令的效果是一样的,试验如下:

    # /etc/init.d/crond stop
    Stopping crond:                                            [  OK  ]
    # /etc/init.d/crond start
    Starting crond:                                            [  OK  ]
    # /etc/init.d/crond status
    crond (pid  4822) is running...
    # /etc/init.d/crond restart
    Stopping crond:                                            [  OK  ]
    Starting crond:                                            [  OK  ]
    # service crond status
    crond (pid  4850) is running...
    # service crond restart
    Stopping crond:                                            [  OK  ]
    Starting crond:                                            [  OK  ]
    # service crond stop
    Stopping crond:                                            [  OK  ]
    # service crond start
    Starting crond:                                            [  OK  ]
    

    当想让某个服务进程开机就自动运行的话,在目录/etc/init.d下创建自己的脚本文件:

    #!/bin/bash
    #
    # test servvice
    #
    # chkconfig: 2345 90 60
    # description: test service
    
    prog=$(basename $0)
    
    if [ $# -lt 1 ]; then
        echo "Usage:$prog {start|stop|status|restart}"
        exit 1
    fi
    
    if [ "$1" == "start" ]; then
        echo "start $prog done"
    elif [ "$1" == "stop" ]; then
        echo "stop $prog done"
    elif [ "$1" == "restart" ]; then
        echo "restart $prog done"
    elif [ "$1" == "status" ]; then
        if [ pidof $prog &> /dev/null ]; then
            echo "$prog is running"
        else
            echo "$prog is stopped"
        fi
    else
        echo "Usage:$prog {start|stop|status|restart}"
        exit 2
    fi
    

    注意:chkconfig: 2345 90 60

    2345:级别

    90:启动优先级

    60:终止优先级

    有个命令chkconfig可以帮助我们,在rc0.d,rc1.d,rc2.d,rc3.d,rc4.d,rc5.d,rc6.d目录下自动创建符号链接,符号链接的名字:S90mySer.sh和K60mySer.sh。但不是在所以目录都创建,根据写的级别创建,这里写的是2345,所以在rc2.d,rc3.d,rc4.d,rc5.d目录下创建S90mySer.sh和K60mySer.sh

    虽然【# chkconfig: 2345 90 60】是注释,但必须有这行。否则,执行chkconfig命令出下面的错误:

    # chkconfig mySer.sh on
    service mySer.sh does not support chkconfig
    

    使用chkconfig mySer.sh on就是在2345目录下创建S90mySer.sh文件

    使用chkconfig mySer.sh off就是在2345目录下创建K90mySer.sh文件

    # chkconfig mySer.sh on
    # ls /etc/rc.d/rc0.d/ | grep mySer
    # ls /etc/rc.d/rc1.d/ | grep mySer
    # ls /etc/rc.d/rc2.d/ | grep mySer
    S90mySer.sh
    # ls /etc/rc.d/rc3.d/ | grep mySer
    S90mySer.sh
    # ls /etc/rc.d/rc4.d/ | grep mySer
    S90mySer.sh
    # ls /etc/rc.d/rc5.d/ | grep mySer
    S90mySer.sh
    # ls /etc/rc.d/rc6.d/ | grep mySer
    # chkconfig mySer.sh off
    # ls /etc/rc.d/rc0.d/ | grep mySer
    # ls /etc/rc.d/rc1.d/ | grep mySer
    # ls /etc/rc.d/rc2.d/ | grep mySer
    K60mySer.sh
    # ls /etc/rc.d/rc3.d/ | grep mySer
    K60mySer.sh
    # ls /etc/rc.d/rc4.d/ | grep mySer
    K60mySer.sh
    # ls /etc/rc.d/rc5.d/ | grep mySer
    K60mySer.sh
    # ls /etc/rc.d/rc6.d/ | grep mySer
    

    有了这些链接文件后,就可以使用service命令,来启动我们的服务了。

    # service mySer.sh start
    start mySer.sh done
    # service mySer.sh stop
    stop mySer.sh done
    # service mySer.sh restart
    restart mySer.sh done
    

    chkconfig选项:

    • 查看:--list [scriptname]

      # chkconfig  --list
      abrt-ccpp       0:off   1:off   2:off   3:on    4:off   5:on    6:off
      abrtd           0:off   1:off   2:off   3:on    4:off   5:on    6:off
      acpid           0:off   1:off   2:on    3:on    4:on    5:on    6:off
      atd             0:off   1:off   2:off   3:on    4:on    5:on    6:off
      auditd          0:off   1:off   2:on    3:on    4:on    5:on    6:off
      autofs          0:off   1:off   2:off   3:on    4:on    5:on    6:off
      # chkconfig  --list mySer.sh
      mySer.sh        0:off   1:off   2:on    3:on    4:on    5:on    6:off
      
    • 指定运行级别:--level LEAVES

      # chkconfig  --list mySer.sh
      mySer.sh        0:off   1:off   2:on    3:on    4:on    5:on    6:off
      # chkconfig --level 35 mySer.sh off
      # chkconfig  --list mySer.sh
      mySer.sh        0:off   1:off   2:on    3:off   4:on    5:off   6:off
      

    当只是单纯开机运行某个进程,而不需要额外的脚本的话,直接修改/etc/rc.d/rc.local文件即可。

    下面添加了touch /tmp/welcome,所以开机后,就会创建这个文件;

    添加了/usr/sbin/httpd,所以开机后,就会启动httpd进程。

    #!/bin/sh
    #
    # This script will be executed *after* all the other init scripts.
    # You can put your own initialization stuff in here if you don't
    # want to do the full Sys V style init stuff.
    
    touch /var/lock/subsys/local
    touch /tmp/welcome
    /usr/sbin/httpd
    

    为什么编辑/etc/rc.d/rc.local文件就好用呢?

    因为这个文件被rc2.d,rc3.d,rc4.d,rc5.d目录里的最后一个文件S99local链接了

    # ll /etc/rc.d/rc2.d/ | tail -1
    lrwxrwxrwx. 1 root root 11 Jan 31 14:08 S99local -> ../rc.local
    # ll /etc/rc.d/rc3.d/ | tail -1
    lrwxrwxrwx. 1 root root 11 Jan 31 14:08 S99local -> ../rc.local
    # ll /etc/rc.d/rc4.d/ | tail -1
    lrwxrwxrwx. 1 root root 11 Jan 31 14:08 S99local -> ../rc.local
    # ll /etc/rc.d/rc5.d/ | tail -1
    lrwxrwxrwx. 1 root root 11 Jan 31 14:08 S99local -> ../rc.local
    

    系统初始化脚本/etc/rc.d/rc.sysinit的作用:

    • 设置主机名

    • 设置欢迎信息

    • 激活udev(创建设备文件用的)和selinux

    • 挂载/etc/fstab文件中定义的所以文件系统

    • 检测根文件系统,没有问题后,以读写方式重新挂载根文件系统。

    • 读取硬件时钟,设置系统时钟

    • 读取配置文件/etc/sysctl.conf里的内核参数,修改内核的行为。

    • 激活lvm及软raid设备

    • 激活swap设备

    • 从根文件系统,加载硬件的驱动程序

    • 清理操作

    总结:/sbin/init的启动流程

    1,通过读取配置文件/etc/inittab,获得运行级别

    2,执行脚本/etc/rc.d/rc.sysinit,完成系统初始化

    3,根据取得的运行级别,先停止这个级别不需要运行的进程(K##),再启动这个级别需要运行的进程(S##)

    4,设置登录终端。如果是级别3则登录终端是文本界面

    5,如果是级别5,则需要启动图形界面服务,显示图形登录界面;

    centos6系统启动流程

    基本和centos5相同,只列出不同点

    1,init程序:upstart,但依然为/sbin/init。其配置文件不是/etc/inittab了,而是/etc/init/*.conf。但/etc/inittab里也有用,只放默认运行级别一行(id:3:initdefault:)。

    2,系统初始化脚本是/etc/init/rcS.conf,但里面运行的是/etc/rc.d/rc.sysinit

    3,脚本/etc/init/rc.conf里面,调用/etc/rc.d/rc $RUNLEVEL

    centos7系统启动流程

    启动流程是一样的,实现的细节不一样。

    兼容centos5和6,所以也可以使用service命令。

    # service crond start
    Redirecting to /bin/systemctl start crond.service
    # service crond status
    Redirecting to /bin/systemctl status crond.service
    

    centos7使用systemctl命令。

    centos7没有了运行级别的概念,改用target概念

    • graphical.target对应运行级别5
    • multi-user.target对应运行级别3

    systemctl get-default

    # systemctl get-default
    graphical.target
    

    centos7的init程序:Systemd

    ​ 使用的配置文件: /usr/lib/systemd/system目录下的文件,和/etc/systemd/system目录下的文件

    # c/c++ 学习互助QQ群:877684253 ![](https://img2018.cnblogs.com/blog/1414315/201811/1414315-20181106214320230-961379709.jpg) # 本人微信:xiaoshitou5854
  • 相关阅读:
    网页自动跳转/定时跳转代码
    阿里云ECS用Xshell安装wdcp教程
    wdcp环境下更新PHP到5.3教程
    WDCP 安装教程,超简单!!
    Jquery select 三级联动 (需要JSON数据)
    Jquery实现循环删除Reaper某一行
    jquery更改Reaper某一列的值
    联系电话正则表达式(jquery表单验证)
    Jquery获取选中的checkbox的值
    sql语句创建主键、外键、索引、绑定默认值
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/12343134.html
Copyright © 2020-2023  润新知