《鸟哥的Linux私房菜》读书笔记:开机流程、模块管理与Loader

Linux开机流程分析

开机流程从上至下:

  • 加载BIOS的硬件信息与进行自我测试,根据设定获取第一个可开机的device
  • 读取并执行上述device中的MBR的boot loader
  • 根据boot loader加载Kernel,Kernel开始侦测硬件与加载驱动程序
  • 硬件驱动完成后,Kernel主动呼叫init程序,init取得run-level信息
  • init执行/etc/rc.d/rc.sysinit档案来准备软件执行的操作环境(网络、时区等)
  • init执行run-level的各个服务
  • init执行/etc/rc.d/rc.local档案
  • init执行终端机仿真程序mingetty来启动login程序,然后等待用户登录

BIOS、boot loader与Kernel载入:

  • BIOS,POST与MBR:BIOS读取CMOS中的各项硬件配置;之后执行POST(上电自检)检查电脑是否良好;接着硬件侦测初始化,包括创建中断向量、设置寄存器、对一些外部设备进行初始化和检测等,其中很重要的一部分是BIOS设置,主要是对硬件设置的一些参数,当电脑启动时会读取这些参数,并和实际硬件设置进行比较,如果不符合,会影响系统的启动;最后是引导DOS或其他操作系统。定义可以开机的设备顺序后,BIOS先从软盘或硬盘的开始扇区读取引导记录,如果没有找到,则会在显示器上显示没有引导设备,如果找到引导记录会把电脑的控制权转给引导记录,由引导记录把操作系统装入电脑,在电脑启动成功后,BIOS的这部分任务就完成了。
  • Boot Loader:开机管理程序,在开机device的第一个扇区中(MBR)。BIOS通过硬件的INT13中断功能来读取MBR。其功能:
    • 最主要功能是识别操作系统的文件格式,根据其格式加载核心到内存中去执行
    • 提供选单:用户可以选择不同的开机项,提供多重引导
    • 载入核心档案:直接指向可开机的程序区来启动操作系统
    • 托付其他loader:将开机管理功能转交给其他loader负责。
      • :windows的loader默认不支持控制权转交,因此装双系统通常先装windows,再装Linux,防止MBR的boot loader被windows loader覆盖。
  • 加载核心侦测硬件initrd的功能:
    • 当boot loader开始管理读取核心时,Linux 会将核心解压到内存当中,利用核心的功能,开始测试驱动和各个周边设备(CPU,声卡,存储设备,网卡等)。此时Linux核心以自己的功能去扫描硬件,开始接管BIOS的工作。kernel档案一般放置在/boot/目录下。
      • 注: Linux核心是可以动态加载核心模块的,核心模块放在/lib/modules/目录下。为了在开机的时候读取核心模块提供加载驱动程序的功能,在开机的过程中必须挂载根目录,因此/与/lib不可放在不同的分区(partition)。
    • Linux初始RAM磁盘(Initial RAM Disk),一般使用的文件名为/boot/initrd。initrd是在系统引导过程中挂载的一个临时根文件系统,用来支持两阶段的引导过程。initrd文件中包含了各种可执行程序驱动程序(通常是USB, RAID, LVM, SCSI ,SATA等文件系统与磁盘接口的驱动程序),它们可以用来挂载实际的根文件系统,然后再将这个 initrd RAM磁盘卸载,并释放内存。在很多嵌入式Linux系统中,initrd 就是最终的根文件系统。等载入完成后, initrd会帮核心重新呼叫 /sbin/init 来开始后续的正常开机流程。
      • 注: initrd并不是必须的,主要取决于你的根目录挂载在什么类型的磁盘和使用的文件系统,使用的是IDE磁盘和默认的ex2/ex3文件系统,那么不需要initrd也可以开机进入Linux。

第一个程序init及配置文件/etc/inittab与runlevel

  • /sbin/init:在核心加载完毕,硬件检测和驱动加载结束后,运行的第一个程序。主要功能是准备软件运行的环境(主机名、网络设定、语系处理、文件系统格式及其他服务的启动)。所有流程通过配置文件/etc/inittab来设定,包括很重要的设定项默认的runlevel
  • Run level功能与等级:Linux通过设定run level让系统使用不同的服务来启动,获取不同的Linux环境。runlevel分为7个等级:
    • 0 - system halt(Do not use this for initdefault! 系统直接关机)
    • 1 - single user mode(单人维护模式,系统维护)
    • 2 - Local multi-user without remote network(e.g NFS)
    • 3 - Full multi-user with network(拥有完整网络功能)
    • 4 - Not used(系统保留)
    • 5 - Full multiuser with network and xdm(与run level3相似,但有X window)
    • 6 -system reboot(Do not use this for initdefault!)

init处理系统初始化流程

  • inittab中有一行为si::sysinit:/etc/rc.d/rc.sysinit,其用来设定系统环境。Suse发行版是用si::bootwait:/etc/init.d/boot来设定。具体的设定文件查看inittab来获知,想知道开机过程中进行了什么动作,可以查看rc.sysinit/boot等相关文件。
  • 可以使用dmesg命令查看开机过程中执行了什么任务。
  • 关于自定义模块加载,将模块写到/etc/sysconfig/modules/*.modules来加载核心模块。

启动系统服务及相关启动配置文件

  • 主要是通过/etc/rc.d/rc来执行相关任务,Suse 路径为/etc/init.d/rc,具体文件路径请在/etc/inittab配置文件下查看。
  • rcX.d(X=012356)目录下的文件都是软链接(符号链接),指向/etc/init.d/目录下的服务,文件以Kxx和Sxx开头(xx为数字,代表执行顺序)。想给指定run level加入自启动服务,chkconfig指令处理链接文件,不需要自行操作。

用户自定义开机启动程序/etc/rc.d/rc.local

任何想要在开机时就进行的工作,直接写入 /etc/rc.d/rc.local , 那么该工作就会在开机的时候自动被加载。

开机过程会用到的主要配置文件

  • /etc/modprobe.conf,模块配置文件,主要指定系统内硬件使用的驱动模块
  • /etc/sysconfig/* 开机过程会用到的配置文件大多放置在此目录下。

Run level 的切换

  • 预设开机启动的run level,修改/etc/inittab配置文件中的id:5:initdefault:数字即可,也就是第二个字段
  • 运行时暂时切换run level,使用init [0-6]命令来切换即可,切换时:
    • 先比对 /etc/rcX.d/ 及 /etc/rcx.d 内的 K 与 S 开头的档案
    • 在新的 runlevel 内有多的 K 开头档案,则予以关闭
    • 在新的 runlevel 内有多的 S 开头档案,则予以启动

核心与核心模块

  • 核心与模块位置:
    • 核心: /boot/vmlinuz 戒 /boot/vmlinuz-version
    • 核心解压所需 RAM Disk: /boot/initrd (/boot/initrd-version)
    • 核心模块: /lib/modules/version/kernel 或 /lib/modules/$(uname -r)/kernel
    • 核心原码: /usr/src/linux (安装才有,预设不安装)
  • 核心被顺利的加载系统当中了,那么就会有几个信息记录下:
    • 核心版本: /proc/version
    • 系统核心功能: /proc/sys/kernel
  • 新的硬件,操作系统不支持的解决办法:
    • 重新编译核心,加入最新的硬件驱动程序原码
    • 将该硬件的驱动程序编译成为模块,在开机时加载该模块

核心模块与相依性:depmod

核心模块是在 /lib/modules/$(uname -r)/kernel中,/lib/modules/$(uname -r)/modules.dep 这个档案记录了核心支持的模块的各项相依性。利用depmod命令建立这个档案。

核心模块的观察:lsmod,modinfo

  • lsmod:查看核心加载了多少模块,包括模块的名称,大小,是否被其他模块使用的信息
  • modinfo:加上模块名称或模块完整文件路径,可查看模块的详细信息

核心模块的加载与移除:insmod,modprobe,rmmod

  • insmod:用户自行加载一个模块,后接模块文件完整路径
  • modprobe:主动分析modules.dep,克服模块相依性后决定加载哪些模块
  • rmmod:移除模块
  • 注:insmod与rmmod需要找到模块的完整文件名,且模块有相依性问题,无法直接加载和移除,因此通常用modprobe处理模块加载问题,modprobe常用option:
    • l:列出目前在 /lib/modules/uname -r/kernel 当中的所有模块完整文件名
    • c:列出目前系统所有的模块
    • f:强制加载该模块
    • r:移除某个模块

核心模块的额外参数设定:/etc/modprobe.conf

如果您想要修改某些模块的额外参数设定, 就在这个档案内设定

Boot loader:Grub

boot loader的两个stage

  • 执行boot loader主程序:这个主程序必须安装在开机区,MBR/boot sector。因为MBR 实在太小了只有446Bytes,所以MBR/boot sector 通常仅安装 boot loader 的最小主程序, 没有安装 loader 的相关配置文件。
  • 主程序加载配置文件:boot loader加载所有配置文件与相关的环境参数档案 (包括文件系统定义主要配置文件 menu.lst), 一般来说,配置文件都在 /boot 目录下。

grub 的配置文件/boot/grub/menu.lst与选单类型:磁盘代号, menu.lst

  • grub较Lilo的优点:
    • 认识支持较多的文件系统,可以使用 grub 的主程序直接在文件系统中查找核心文件
    • 开机的时候,可以自行编辑、修改开机设定项目
    • 可以动态搜寻配置文件,而不需要在修改配置文件后重新安装 grub。设定下次开机就生效。
  • 硬盘与分区在 grub 中的代号:
    • 硬盘代号以小括号 ( ) 包起来
    • 以搜寻顺序做为硬盘的编号,不是依照硬盘扁平电缆的排序!
    • 第一个搜寻到的硬盘为 0 号,第二个为 1 号,以此类推,每颗硬盘的第一个partition代号为0,依序类推。
  • /boot/grub/menu.lst 配置文件
    • 直接指定核心开机
      • 先指定核心档案放置的分区,再读取文件路径, 最后加入档案的实际文件名与路径 (kernel和initrd)
        root (hd0,0) <==代表核心档案放在那个分区当中
        kernel /vmlinuz-XXXXX ro root=LABEL=/1 rhgb quiet
        initrd /initrd-XXXXX
      • 直接指定分区和文件名,不需要额外指定核心文件所在device代号
        kernel (hd0,0)/vmlinuz-XXXX ro root=LABEL=/1 rhgb quiet
        initrd (hd0,0)/initrd-XXXXX
    • 利用 chain loader 的方式转交控制权:
      • chain loader 的设定只要两个就够了,一个是转交的 boot sector 所在的分
        区代号, 另一个是设定 chainloader 在那个分区的 boot sector (第一个扇区) 上。
        root (hdX,X) <==设定使用此分区
        chainloader +1 <== +1 可以想成第一个扇区,也就是 boot sector

initrd 的重要性和建立新 initrd 档案: mkinitrd

  • initrd的必要性:核心模块位于 /lib/modules/$(uname -r)/kernel/ 当中, 这些模块必须要根目录 (/) 被挂载后才能被读取。但是如果核心本身不具备磁盘的驱动程序时, 当然无法挂载根目录,也就没有办法取得驱动程序,we are in a dilemma.
  • initrd作用:将开机过程中必须的模块包装成一个文件,通过INT13硬件功能读取此文件,initrd在内存中仿真为根目录。因为initrd主要包含磁盘和文件系统模块,核心就能够识别真实的磁盘并进行实际根目录挂载操作。
  • 需要initrd的情况一般有:
    • 根目录所在磁盘为 SATA、USB 与 SCSI 等连接接口
    • 根目录所在文件系统为 LVM, RAID 等特殊格式
    • 根目录所在文件系统为非传统 Linux 认识的文件系统时
    • 其他必须要在核心加载时提供的模块
  • mkinitrd重制initrd文件:有特殊需要可以用此命令来制作initrd
    • mkinitrd [-v] [文件名][核心版本$(uname -r)]#默认功能建立一个initrd档案
    • mkinitrd [--with=模块名称][文件名][核心版本]#增加某个模块到对应initrd档案

测试安装 grub: grub-install, grub shell

  • 安装grub:许多发行版都是安装了grub,若没有安装则使用grub-install命令安装,grub-install [--root-directory=DIR] install_device,DIR是安装路径,install_device是安装的磁盘或分区。DIR默认为/boot/grub
  • grub shell:
    • root (hdx,x)选择有grub目录的那个partition
    • find /boot/grub/stage1安装信息档案
    • setup(hdx,x)setup (hdx) 将grub主程序安装在boot sector或MBR

关于核心功能当中的 vga设定

如果核心支持FRAMEBUFFER_CONSOLE,则可以修改tty1-tty6的分辨率。grep 'FRAMEBUFFER_CONSOLE' /boot/config-XXX来查询是否支持。 在menu.lst选单kernel那一行后面加上vga=XXX(X为数值)则可以设置相应的分辨率。

BIOS无法读取大硬盘的问题

让kernel和initrd文件放在大硬盘的最前头,BIOS 至少可以读到大磁盘的 1024 磁柱内的数据,因此就能够读取核心和虚拟文件系统的文件。那如何把kernel和initrd放到整颗硬盘的最前面,就建立/boot 独立分割槽,将/boot放置到最前面即可。

开机过程的问题解决

忘记 root 密码

  • 重启
  • 在开机进入 grub 选单后:
    • (1)在你要进入的选单上面点 ‘e’ 进行详细设定;
    • (2)将光标移动到 kernel 上方点 ‘e’ 进入编辑画面;
    • (3)然后在最后加上single,按下 [enter] 再按下 b 就能够开机进入单人维护模式了。
  • 进入单人维护模式后,系统会以 root 的权限直接给你一个shell,此时你就能够执行passwd这个命令来重置root的密码。然后直接init 5就可以切换成为 X 窗口接口。

init 配置文件错误

前一个 root 密码挽救的方法其实可以用在很多地方,唯一无法挽救的情况就是 /etc/inittab 这个档案设置错误导致无法开机。在grub选单中编辑,在kernel一行最后加上init=/bin/bash指定第一个运行的程序为bash,/sbin/init不会被执行。但此时只有根目录被挂载,且为只读状态mount -o remount,rw /重新挂载根目录且设定为可读写,mount -a参考/etc/fstab内容重新挂载文件系统。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值