zoukankan      html  css  js  c++  java
  • linux文件系统启动流程、启动脚本

    linux文件系统启动流程、启动脚本

    下面是一张Linux启动流程图:

    在了解启动流程之前,我们应该先知道系统的几个重要脚本和配置文件,他们对应的路径为:

    1. /sbin/init

    2. /etc/inittab

    3. /etc/rc.d/rc.sysinit

    4. /etc/rc.d/rcN.d //这是几个文件夹N代表数字1,2,3,4..

    5. /etc/fstab

    1.关于/sbin/init与/etc/inittab

    关于/sbin/init ,它是一个二进制可执行文件,为系统的初始化程序,而/etc/inittab是它的配置文件,我们可以通过/etc/inittab来一睹 它的功能, 里面的内容是一种固定的文本格式,id:runlevels:action:process

    我们来通过它的内容来学习它之前,先了解写运行级别的分类(0-6):

    0: 关机 half

    1: 单用户模式 singel user

    2: 多用户模式 multi user , 不提供nfs服务 without nfs

    3: 完全多用户字符模式 full multiuser text mod

    4: 系统预留 officially undefined

    5: 图形登录界面 graphical login

    6: 重启 reboot

    [html] view plain copy
     
     
    1. id:3:initdefault:                             //这里定义linux的启动时的运行级别,可以看到我主机的启动级别是3  
    2. # System initialization.  
    3. si::sysinit:/etc/rc.d/rc.sysinit     //紧接着,运行系统第一个脚本/etc/rc.d/rc/sysinit      
    4.                                                //它的action:sysyinit指的是定义系统初始化过程  
    5. l0:0:wait:/etc/rc.d/rc 0                            
    6. l1:1:wait:/etc/rc.d/rc 1                             
    7. l2:2:wait:/etc/rc.d/rc 2                  //然后就是加载服务了,他们被定义在/etc/rc.d/rcN.d  
    8. l3:3:wait:/etc/rc.d/rc 3                  //action:waite 这个进程在在对应级别启动一次,直到它结束为止,我的系统启动级别为3,所有执行rc 3对应的服务  
    9. l4:4:wait:/etc/rc.d/rc 4  
    10. l5:5:wait:/etc/rc.d/rc 5  
    11. l6:6:wait:/etc/rc.d/rc 6  
    12.                             
    13. ca::ctrlaltdel:/sbin/shutdown -t3 -r now     //这里定义了一个组合快捷键,熟悉吧,没错就是重启,你可以把它注释掉不用     
    14. pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"  //这里定义了ups电源,powerfail 指的是如果突然断电,它对应的process命令是,提示用户系统电源失效,将要关机,提醒用户把数据都存储好  
    15. pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"  //这里的action,powerokwaite,指的是系统恢复供电,关机取消...  
    16.   
    17. 1:2345:respawn:/sbin/mingetty tty1           //开启终端,在系统准备工作做好后,就会启动出6个终端,tty1~6 mingetyy就是终端的执行命令  
    18. 2:2345:respawn:/sbin/mingetty tty2           //可以看到他们对应的级别是2345,你也可以注释掉几个,这样启动后,就会开启你指定个数的终端...   
    19. 3:2345:respawn:/sbin/mingetty tty3           //这里的动作respawn意思是如果用户关闭,那么这个进程会立刻再次执行   
    20. 4:2345:respawn:/sbin/mingetty tty4  
    21. 5:2345:respawn:/sbin/mingetty tty5  
    22. 6:2345:respawn:/sbin/mingetty tty6  
    23. x:5:respawn:/etc/X11/prefdm -nodaemon       //当一切准备完毕,就会运行守护进程,它是不分运行级别的,同样也是respawn  

    2. 关于etc/rc.d/rc.sysinit 和 /etc/rc.d/rc.Nd

    在inittab文件中,我们了解到rc.sysinit是系统运行的第一个脚本,那么它的作用都有哪些呢?如果有shell脚本基础的话可以用vim打开这个文件来看看,它有900多行...是linux里最牛的脚本,总结下它的作用,有如下几点:(一定要牢记,必要时我们要重写它!)

    1. 激活udev和selinux

    2. 通过读取/etc/sysct1.conf来设置内核参数

    3. 设置系统时钟

    4. 设置键盘映射

    5. 启动交换分区。

    6. 设置主机名

    7. 检查根文件系统,如果没有错误,以读写的方式来重新挂载文件系统 (重要)

    8. 激活raid和lvm设备

    9. 启动磁盘限额

    10 挂载其他/etc/fstab里定义的尚未被挂载的设备

    11. 清理过时的文件锁和PID文件

    12. 启动服务/etc/rc.d/rcN.d

    /etc/rc.d/rcN.d 是一个存放了系统启动是加载的服务的文件夹,通过inittab,我们知道了,它的编号对应相应的启动运行级别。

    需要说明的是,它里面的文件,以我的为例 以K开头的代表stop,以S开头的代表启动start,数字越小,有限级别越高

    [html] view plain copy
     
     
    1. [root@server69 rc.d]# cd rc3.d  
    2. [root@server69 rc3.d]# ls  
    3. K01dnsmasq         K74nscd             S08ip6tables    S25bluetooth   S85gpm  
    4. K02avahi-dnsconfd  K85mdmpd            S08iptables     S25netfs       S90crond  
    5. K02NetworkManager  K87multipathd       S08mcstrans     S25pcscd       S90xfs  
    6. K05conman          K88wpa_supplicant   S10network      S26acpid       S95anacron  
    7. K05saslauthd       K89dund             S11auditd       S26apmd        S95atd  
    8. K10psacct          K89netplugd         S12restorecond  S26haldaemon   S97rhnsd  
    9. K20nfs             K89pand             S12syslog       S26hidd        S97yum-updatesd  
    10. K24irda            K89rdisc            S13irqbalance   S28autofs      S98avahi-daemon  
    11. K35vncserver       K99readahead_later  S13portmap      S50hplip       S99firstboot  
    12. K35winbind         S00microcode_ctl    S14nfslock      S55sshd        S99local  
    13. K50ibmasm          S02lvm2-monitor     S15mdmonitor    S56cups        S99smartd  
    14. K50netconsole      S04readahead_early  S18rpcidmapd    S56rawdevices  
    15. K69rpcsvcgssd      S05kudzu            S19rpcgssd      S58ntpd  
    16. K73ypbind          S06cpuspeed         S22messagebus   S80sendmail  

    3./etc/fstab文件

    它定义了系统初始化挂载的设备,对系统的启动至关重要,rc.sysinit通过读取它来实现系统分区的挂载

    它的内容如何呢?我们一起来看下

    要挂载的设备 挂载点 文件系统类型 挂载选项 转储频率 文件自检次序

    [html] view plain copy
     
     
    1. /dev/sda2               /                       ext3    defaults        0 0  
    2. /dev/sda1               /boot                   ext3    defaults        0 0  
    3. sysfs                   /sys                    sysfs   defaults        0 0  
    4. proc                    /proc                   proc    defaults        0 0  

    我截取了4个系统启动时必须挂载的设备

    / 根文件目录,由它你才可以进入linux的世界,它在/dev/sda2里

    /boot 启动目录,在/下,里面有grub,initrd和系统内核,它在/dev/sda1

    sysfs 一个虚拟的文件系统,产生包含所有硬件层次视图,和/proc类似

    proc 这是一个虚拟的目录,它映射内存里的信息对应进程信息,也就是说它对应的是内存而不是硬盘

    好了,了解了这些文件和目录的作用,我们在回过头来看那张流程图:

    1. linux开机从POST加电自检开始,当自检完成,读取第一个硬盘的第0个磁头里的前446个字节,运行里面的bootloader,linux一般   用的是grub。
    2. 通过grub传递参数给内核,初始化加载内核过程,内核调用initrd(小型内存文件系统,五脏俱全,是一个微型linux),通过     initrd,以只读方式挂载根文件系统
    3. 当根文件系统被挂载后,就会读取并运行/sbin/init来进行初始化工作。
    4. 按次序依次执行/rc/sysinit ,这个时候会重新以读写的方式挂载根文件系统
    5. 读取/etc/rc.d/rcN.d/来启动以s开头的服务,停止以k开头的服务
    6. 当一切准备完毕,打印终端,出现熟悉的Login界面!(当然,如果你是以5级别启动的话,Linux就会启动图形界面~)

     运行一个linux系统需要三项内容:
       1,kernel, 内核,一些核心的代码块,如进程管理,它要求体积很小。
       2,initrd, 进入系统所需预告加载的硬件驱动module的一个最小集。当GRUB加载kernel时,kernel会在内存中将initrd文件mount到rootfs上激活,然后kernel照着initrd中的init一步一步地加载驱动。在initrd文件中所放入的模块,必须是与操作系统同一版本kernel所编译的模块。init脚本的工作流程是:
          initrd的参考文档可见:
          1) Linux initial RAM disk (initrd) overview, http://www.ibm.com/developerworks/linux/library/l-initrd/index.html
          2)  NTTdocomo-openstack / baremetal-initrd-builder, https://github.com/NTTdocomo-openstack/baremetal-initrd-builder
          2.1, nash指令(一个文件小,内置了一些实用的指令)
          2,2 挂载主要的文件系统, 并建立设备文件所需的文件系统
             mount -t proc /proc /proc
             mount -t sysfs /sys /sys
                2.2.1,procfs映射着内存中的一个虚拟目录,用于提供硬件、进程的实时信息,会随时变动。linux为保证稳定性,不允许访问/proc下的文件,root用户也不例外。
                2.2.2, sysfs也映射着内存中的一个虚拟目录,用于硬件信息的分类, sys目录的每一个文件都只有一个字符为内容来做开关的。
                2.2.3, tmpfs也映射着内存中的一个虚拟目录,内存中的文件系统。想要速度快时,可以选择在内存建立tmpfs类型的文件系统,因为它都将建在内存中。
                       例如在内存中建立了一个tmpfs分区并挂载到/mnt/tmpfs目录 :mount -t tmpfs -o size=50M tmpfs /mnt/tmpfs/
                            [root@zhanghua proc]# df -h
                            Filesystem      Size  Used Avail Use% Mounted on
                            tmpfs            50M     0   50M   0% /mnt/tmpfs
                2.2.4, /dev/shm,它是tmpfs的一种变种,tmpfs所有的内容所放在内存中,而/dev/shm在内存与文件系统有个映射,硬盘和内存中都会有这内容。
                      速度快,能存大于内存的文件,但重启之后,内容会消失。
                      下面显示在/dev/shm中建立文件与在普通ext4文件系统建文件的速度比较:
                            [root@zhanghua proc]# time dd if=/dev/zero of=/dev/shm/test.file bs=1M count=100
                100+0 records in
                100+0 records out
                104857600 bytes (105 MB) copied, 0.0395221 s, 2.7 GB/s

                real    0m0.075s
                user    0m0.001s
                sys    0m0.041s
                [root@zhanghua proc]# time dd if=/dev/zero of=/bak/test.file bs=1M count=100
                100+0 records in
                100+0 records out
                104857600 bytes (105 MB) copied, 0.0647526 s, 1.6 GB/s

                real    0m0.090s
                user    0m0.001s
                sys    0m0.066s
                2.2.5,devfs, 所有的device都会在/dev目录建立一个对应的设备文件.
                       缺点是例如即使打印机没连在计算机上,/dev/printer文件也会存在,这样会造成在intrd阶段的设备过多,所以devfs正在被udev所取代
                       例如要用光驱时,需先在linux与光驱之间通过 mount /dev/cdrom /mnt/命令做关联
                2.2.6, udev, udev可以放在/sys目录下,不需要将所有未使用的文件建立设备文件,不再需要major number和minor number,当硬件被加载时可执行用户设置的script。
                       例如,如果/dev/cdrom是被udev建立的,而非devfs,那么当光驱被拨除时,/dev/cdrom文件就会消失。
                2.2.7,/proc/PID文件,第一个进程都会对应这要闰个文件
                2.2.8,/proc/partitions用来表示检测到的硬盘信息, major字段表示SCSI controller的slot ID,minor字段表示分区ID。
                      #[root@zhanghua proc]# cat /proc/partitions  
               major minor  #blocks  name
                   8        0  488386584 sda
                   8        1   82051956 sda1
                2.2.9, /sys/block,块设备
                      #[root@zhanghua proc]# cat /sys/block/
                        loop0/ loop1/  sda/   sr0/
                2.2.10, /dev/pts ( pseudo terminal slave) 副虚拟终端,其目录的文件都是由ptmx(主虚拟终端)产生的,它们是父子关系。当用ssh联机到localhost本地端之后,就会在
                       /dev/pts目录下产生一个叫做"0"的文件,当别的console也利用ssh联到这台机器时,就会出现“1“.
                      [root@zhanghua proc]# ps -ef|grep ssh
                       hua      11186  3068  0 16:01 pts/0    00:00:00 ssh hua@localhost  
                       hua      11195 11187  0 16:01 ?        00:00:00 sshd: hua@pts/3
                       如上,当一个用户以ssh登录之后,该用户就分到一个ptmx所赋予的pts资源(pts/3),所以说ssh使用的是虚拟终端,不是真正的tty接口。telnet用的则是真正的tty接口。
                2.2.11, /dev/mapper,如果使用LVM后,linux要和硬盘打交道时不再直接使用/proc/partitions下的硬盘设备,而是使用/dev/mapper下的设备再去中转。
                        # ls -l /dev/mapper/*
                          brw-rw---- 1 root disk 253, 0 jan 27 16.16  /dev/mapper/vg0-lv0
                        # cat /proc/partitions
                          major minor #blocks name
                           8     0     17528  sda
                           253   0     1111   dm-0
          3,建立最初所需使用的设备文件
             设备文件使用mknod指令建立,mknod指令用来建立字符(character)或块(block)文件。
             例:mknod /dev/tty1c41, 建立一个名为tty1的设备文件,c表示是字符文件,major=4, minor=1
          4,加载相关模块
          5,切入image所指示的硬盘中实体操作系统. (rescue mode是直接通过kernel加载initrd进入单纯的内存开机的虚拟操作系统)
             5.1, mkrootdev -t ext4 -o defaults.ro hda1, 即nash指令会将GRUB中所设备的root=xxx中的xxx路径先建立好
             5.2, mount /sysroot, 将GRUB中的root路径mount到initrd中的/sysroot下。
             5.3, switchroot这个nash指令将initrd中的/sysroot文件系统切换成/rootfs,从而切换到了硬盘中的文件系统。
       3,image, 操作系统的image文件系统,当initrd被加载后,必须为用户与文件系统牵线。
       4, init进程,在切入到用户操作系统之后,首先执行linux的init进程(pid=1), init进程再去加载/etc/rc.d/init.d/functions从而启动服务。
          关于启动级别与init进程的事儿,也可参见我的另一博文件,Linux的运行级别与解决开机故障一例 ( by quqi99 ), http://blog.csdn.net/quqi99/article/details/7436926
       5, 系统管理
          5.1, 查看CPU信息 cat /proc/cpuinfo
          5.2, 查看内存, cat /proc/meminfo 或者 free -m
          5.3, 查看usb, lsusb
          5.4, 查看PCI, lspci
          5.5, 查看开机日志, dmesg |grep -i error


       本文讲的是如何编译kernel,接下来也会研究如何制作initrd与image.
       最好使用普通用户执行下面所有操作。
    1,下载内核源码
       git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
       用git tag查看版本,将并代码切换到v3.8-rc5下, git checkout v3.8-rc5
    2,配置内核(有点类似于./configure), 配置前先安装一个依赖包, sudo yum install ncurses-devel,
       make menuconfig
       说明一下,内核的配置项是三选一,yes, no, 或module。yes, no意味着直接将该特性编译或不编译到内核中,module意味着以模块形式编译,模块意味着你开机会可以通modprobe命令动态加载或卸载。
       我在这里选择的默认配置,生成的配置位于根目录下的.config文件之中。
       如果你在一个老的配置文件上更改配置的话,可以用make oldconfig命令比较与之前的配置文件的差异来验证你配置的正确性。
    3,执行make命令编译,
       make
       说明一下,这条命令实际上已经包括了下面的命令:
       1)确定依赖性 make dep
       2)清理编译中间文件,make clean
       3)编译内核, make bzImage
       4)生成模块, make modules
    4, 安装模块,下列命令会将模块自动安装到/lib/modules/3.8.0-rc5/目录下.
       sudo make modules_install

    5, 安装内核及initrd,人工将arch/x86/boot/bzImage的内核文件拷到/boot目录即可。
       sudo cp arch/x86_64/boot/bzImage /boot/vmlinuz-3.8.0-rc5
       sudo chmod a+x vmlinuz-3.8.0-rc5

       sudo update-initramfs -u -k version 

      sudo update-grub -o /boot/grub/grub.cfg
       注意:以vmlinuz-<version>这样命名它。

      上述三步等价于make install, 但make install在自动执行update grub命令时有时候会破坏你的grub文件,特别对于进行PGP加密过的硬盘。

    6,「可选」,安装符号表,只有调试时才需要用到。符号表System.map用以将内核符号和它们的起始地址对应起来,调试的时候,如果需要把内存地址翻译成容易理解的函数名和以及变量名,就会很有用。

       sudo cp System.map /boot/System.map-3.8.0-rc5
    7, 建立initrd文件
       sudo mkinitrd --with=ntfs -o /boot/initrd-linux3.8.0-rc5.img 3.8.0-rc5
       以上mkinitrd命令是参照现有系统的/etc/modprobe.conf和/etc/fstab文件创建一个全新的initrd, 用--with=ntfs会从/lib/modules/3.8.0-rc5目录将ntfs模块也做到initrd里去。

       那如何要从头开始做一个initrd呢?
       1) 可以用 sudo zcat initrd-linux3.8.0-rc5.img | cpio -id 命令解压 ( initrd文件是以ext2作为文件系统中,所以可以用mount -o loop initrd.img /mnt命令加载.)
       2) 然后将模块ntfs.ko加到相应的目录,如lib/modules/3.8.0-rc5/kernel/fs/ntfs目录
       3) 将ntfs.ko模块加到init脚本
       4) 重新压缩,find | cpio -co | gzip -9 > initrd-new.img

    8, 更新grub, 编译/etc/grub/grub.conf文件,添加下面内容,注意千成不要用update grub命令来更新grub哦,这可能会导致你的双系统无法用。
       menuentry 'Fedora,Linux 3.8.0' --class fedora --class gnu-linux --class gnu --class os {
            set root='(hd0,msdos9)'
            linux   /boot/vmlinuz-3.8.0-rc5 root=/dev/sda10 ro   quiet splash
            initrd /boot/initrd-linux3.8.0-rc5.img
       }

       也可以在开机时按e进入grub编辑模式,再按e一次进入kernel的设置界面:
       grub> root (hd0,msdos9)
       grub> kernel /boot/vmlinuz-3.8.0-rc5 ro root=/dev/sda9 acpi=off (注意,kernel在前的grub>光标后一定要空一行)
       grub> initrd /boot/initrd-linux3.8.0-rc5.img

       grub> boot

  • 相关阅读:
    使用存储过程查询并按每页10条记录分页显示图书借阅纪录
    两个div并排 左边div宽固定 右边自适应
    java比较时间及时间的转换
    java使用commons.io的FileUtils进行文件拷贝
    实现image宽度100%,高度与宽度一致
    vue请求前的loading动画效果
    vue项目加载前空白的动画过渡效果
    element-ui和semantic-ui冲突的解决方法--局部引入semantic-ui的css
    vue使用formdata上传多个图片,springboot以文件数组的形式接受
    快速创建vuepress项目(使用vuepress写文档)
  • 原文地址:https://www.cnblogs.com/guxuanqing/p/9511191.html
Copyright © 2011-2022 走看看