0. 启动流程一览
- 1.加载BIOS的硬件信息与进行自我测试, 并依据设置取得第一个可启动的设备(1st device)
- 2.读取并执行第一个启动设备内MBR的boot loader(即是grub, spfdisk等程序)
- 3.依据boot loader的设置加载Kernel, Kernel检测硬件和加载驱动
- 4.在硬件驱动成功后, Kernel主动调用init进程, 而init会取得run-level信息
- 5.init执行/etc/rc.d/rc.sysinit文件来准备软件的操作环境(如网络, 时区等)
- 6.init执行run-level的各个服务的启动(script方式)
- 7.init执行/etc/rc.d/rc.local文件
- 8.init执行终端机模拟程序mingetty来启动login进程, 最后等待用户登录
# rhgb = redhat graphical boot - This is a GUI mode booting screen with most of the
# information hidden while the user sees a rotating activity icon spining and brief
# information as to what the computer is doing.
# quiet = hides the majority of boot messages before rhgb starts. These are supposed
# to make the common user more comfortable. They get alarmed about seeing the kernel # and initializing messages, so they hide them for their comfort.
1. BIOS, boot loader与kernel加载
1. BIOS, 开机自我检测与MBR
BIOS --CMOS(取得硬件配置信息)--> 开机自检(Power-on Self Test, POST) --> 执行硬件检测初始化并配置PnP设备(Plug and Play, 即插即用设备) --> 定义可启动的设备顺序 --> 启动设备的读取(MBR相关任务的开始)
由于不同的操作系统的文件系统格式不同, 必须要以对应的boot loader处理内核文件的加载问题
2. BOOT Loader的功能
系统的MBR只有一个, 如何同时在一部主机上安装Windows与Linux呢?
每个操作系统都默认安装一套boot loader到它自己的文件系统中, 而linux在系统安装时, 你可以选择将boot loader安装到MBR中, 也可以选择不安装, 至于windows默认会主动将MBR与boot sector都装上一份boot loader
boot loader提供的主要功能如下:
1.提供菜单
2.加载内核文件
-
3.转交其他loader
由于windows的loader默认不具有控制权转交功能, 因此你不能使用windows的loader来加载linux的loader
BIOS无法读取大容量硬盘 (内的kernel与initrd文件) 的问题:
系统使用DVD启动安装时, 可以顺利安装Linux, 但是第一次启动时, 屏幕出现一片黑, 且出现grub>的字样, 而无法进入Linux系统中, 这是什么问题?
- 使用DVD或CD启动时, 加载内核不是问题, 而内核回去检测系统硬件, 因此可以识别BIOS识别不到的硬盘, 故你确实可以在大容量硬盘上安装Linux且不出现问题
- 但是进入硬盘启动时, 由于kernel与initrd文件都是通过BIOS的INT 13通道读取的, 因此你的kernel与initrd若放置在BIOS无法读取到的扇区当中, 系统当然无法加载
如何解决?
- 将kernel与initrd文件放在大硬盘的最前面, 由于BIOS至少可以读取到大磁盘的1024柱面的数据, 股就能读取内核与虚拟文件系统的文件
- 那么怎么做呢? 新建/boot独立分区, 并将/boot放置到最前面即可
3. 加载内核与检测硬件与initrd的功能
通过boot loader的管理而开始读取内核文件后, linux会将该内核解压到内存中, 利用内核的功能, 重新检测一次硬件, 而不一定会用BIOS检测到的硬件信息, 也就是说, 内核此时才开始接管BIOS后的工作
内核文件路径: /boot/vmlinuz
ls --format=single-column -F /boot
aquota.group
aquota.user
config-2.6.32-642.el6.x86_64 #此版本内核被编译时选择的功能与模块配置文件
efi/
grub/ #引导装载程序grub相关数据目录
initramfs-2.6.32-642.el6.x86_64.img
initrd-2.6.32-642.el6.x86_64kdump.img #虚拟文件系统文件
lost+found/
symvers-2.6.32-642.el6.x86_64.gz
System.map-2.6.32-642.el6.x86_64
vmlinuz-2.6.32-642.el6.x86_64* #内核文件, 非常重要!!!
linux内核是可以动态加载内核模块的, 由于模块放置在磁盘根目录内(要记得 /lib 与 / 必须放在同一分区), 启动过程中内核必须挂载根目录, 才能读取内核模块提供加载驱动的功能
USB, SATA, SCSI等磁盘设备的驱动程序通常以模块的方式存在
现在思考一种情况, 假设你的linux安装自SATA硬盘上, 你可以通过BIOS的INT13取得boot loader与kernel文件来启动, 然后kernel会开始接管系统, 检测硬件并尝试挂载根目录来取得额外的驱动程序, 问题是: 内核根本不认识SATA磁盘, 所以需要加载SATA磁盘的驱动程序, 否则无法挂载根目录, 但是SATA的驱动程序在/lib/modules内, 你根本无法挂载根目录, 又怎么读取到/lib/modules内的驱动程序呢?
-
虚拟文件系统(initial RAM disk) 一般使用的文件名为
/boot/initrd
, 它的特色是, 也能通过boot loader加载到内存中, 然后这个文件会被解压并在内存中仿真成一个根目录, 能够提供一个可执行的程序, 通过该程序来加载启动过程中最需要的内核模块, 这些模块就是USB, RAID, LVM, SCSI等文件系统与磁盘接口的驱动程序
是否没有initrd就无法顺利启动?
不见得, 最需要initrd的原因, 当启动时无法挂载根目录的情况下, 此时就一定需要initrd, 例如你的根目录在特殊的磁盘接口(USB, SATA, SCSI), 或者你的文件系统较为特殊(LVM, RAID等), 才会需要initrd
2. 第一个进程init及配置文件/etc/inittab与runlevel
内核硬件检测完毕与驱动程序加载后, 此时你的主机硬件以准备就绪(ready), 此时内核会主动调用第一个进程: /sbin/init
, 它最主要的功能就是准备软件执行的环境, 包括系统的主机名, 网络设置, 语系处理, 文件系统格式以及其他服务的启动等, 而所有的操作都会通过init的配置文件/etc/inttab
来规划, 其中一个很重要的设置选项, runlevel
, (启动执行等级)
-
runlevel: 执行等级, linux通过设置runlevel来规定系统启动不同的服务
0 - halt (关机)
1 - singer user mode (单用户维护模式)
2 - multi-user, without NFS (类似runlevel3, 无NFS服务)
3 - full-multi-user mode (完整含有网络功能的纯文本模式)
4 - unused (系统保留功能)
5 - X11(与runlevel类似, 加载使用X window)
6 - (重启)
注: 不可将默认设置为0, 4, 6这三个值, 否则系统会不断的关机或重启
不正常关机造成文件系统的不一致现象时, 系统会主动进入单用户维护模式
#inittab的内容与语法
vi /etc/inittab
id:5:initdefault: #默认的runlevel设置, 此时runlevel为5
si::sysinit:/etc/rc.d/rc.sysinit #准备系统软件执行的环境的脚本执行文件
#7个不同的runlevel, 需要启动的服务的script放置路径:
10:0:wait:/etc/rc.d/rc 0
11:1:wait:/etc/rc.d/rc 1
12:2:wait:/etc/rc.d/rc 2
13:3:wait:/etc/rc.d/rc 3
14:4:wait:/etc/rc.d/rc 4
15:5:wait:/etc/rc.d/rc 5
16:6:wait:/etc/rc.d/rc 6
#是否允许按下 [ctrl] + [alt] + [del] 就重新启动的设置选项:
ca::ctrlaltdel:/sbin/shutdown -t 3 -r now
#tty1-tty6是由这六行决定的:
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
#X window是由这行决定的:
x:5:respawn:/etc/X11/prefdm -nodaemon
[设置选项]:[runlevel]:[init的操作行为]:[命令选项]
1.设置选项: 最多四个字符, 只是一个简单的说明
2.runlevel: 如果是35则表示runlevel 3/5都会执行
3.操作行为: 如下表
4.命令选项: 可进行的命令, 通常是一些script
inittab设置值 | 意义说明 |
---|---|
initdefault | 默认的runlevel设置值 |
sysinit | 系统初始化的操作选项 |
ctrlaltdel | 代表cril+alt+del三个按键是否可以重启的设置 |
wait | 后面字段设置的命令项目必须要执行完毕才能继续下面的其他操作 |
respawn | 后面字段的命令可以无限再生, 例如: tty1的mingetty产生的登录界面, 在你注销后, 系统会再开一个新的可登陆界面等待下一个登录 |
3. init处理系统初始化流程(/etc/rc.d/rc.sysinit)
开始各项系统服务之前, 先得设置好整个系统环境, 主要利用的就是/etc/rc.d/rc.sysinit
主要工作大致如下:
- 1.取得网络环境与主机类型
- 2.测试与挂载内存设备/proc即USB设备/sys
- 3.决定是否启动SElinux
- 4.启动系统随机生成器
- 5.设置终端机(console)字体
- 6.设置显示于启动过程中的欢迎界面(textbanner)
- 7.设置系统时间(clock)与时区设置: 需读入
/etc/sysconfig/clock
的设置值 - 8.接口设备的检测与Plug and Play(PnP)参数的测试
- 9.用户自定义模块的加载:
/etc/sysconfig/modules/*.modules
- 10.加载内核的相关设置: 系统会主动读取
/etc/sysctl.conf
的设置值, 使内核成为我们想要的样子 - 11.设置主机名与初始化电源管理模块(ACPI)
- 12.初始化软件磁盘阵列: 主要通过
/etc/mdadm.conf
来设置 - 13.初始化LVM的文件系统设置
- 14.以fsck检验磁盘文件系统: 会进行filesystem check
- 15.进行磁盘配额quota的转换(非必要)
- 16.重新以可读写模式挂挂载系统磁盘
- 17.启动quota功能: 所以我们不需要自定义quotaon的操作
- 18.启动系统的伪随机数生成器(pseudo-random)
- 19.清除启动过程中的临时文件
- 20.将启动相关信息加载
/var/log/dmesg
文件
4. 启动系统服务与相关启动配置文件(/etc/rc.d/rc N & /etc/sysconfig)
经过/etc/rc.d/rc.sysinit
的系统模块与相关硬件信息的初始化后, 你的CenOS系统应该已经顺利工作了, 只是, 我们还得要启动系统所需要的各项服务啊!
那么各个不同的runlevel服务启动的的各个shell script放在哪?在/etc/inittab
中提到的:
10:0:wait:/etc/rc.d/rc 0
11:1:wait:/etc/rc.d/rc 1
12:2:wait:/etc/rc.d/rc 2
13:3:wait:/etc/rc.d/rc 3
14:4:wait:/etc/rc.d/rc 4
15:5:wait:/etc/rc.d/rc 5 #本例中, 以此选项来解释
16:6:wait:/etc/rc.d/rc 6
- 通过外部第一号参数($1)来取得想要执行的脚本目录, 即由
/etc/rc.d/rc 5
可以取得/etc/rc.d/
这个目录来准备相关处理的脚本程序 - 找到
/etc/rc5.d/K??*
开头的文件, 并进行/etc/rc5.d/K??*stop
的操作 - 找到
/etc/rc5.d/S??*
开头的文件, 并进行/etc/rc5.d/S??*start
的操作
/etc/rc5.d
内全部是连接文件, 连接到stand alone服务启动的目录/etc/init.d/
去, super daemon与stand alone的服务主要是以/etc/init.d/服务文件名{start,stop}
来启动与关闭的, 也就是说, 如果你有想要启动改runlevel是就执行的服务, 那么利用S??并指向/etc/init.d/
的特定服务启动脚本后, 该服务就会在启动时启动, chkconfig
就是在负责处理这个连接文件, S或K后面的数字, 代表执行的顺序, 数字越小越先被执行*
5. 用户自定义开机启动程序(/etc/rc.d/rc.local)
/etc/rc.d/rc.local
这个文件可以在启动时执行你自己想要执行的系统命令
6. 根据/etc/inittab的设置加载终端机或X Window界面
在完成了系统所有服务的启动后, 接下来Linux就会启动终端机或者是X Window来等待用户登录, 实际参考/etc/inittab
内这一段:
#tty1-tty6是由这六行决定的:
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
#X window是由这行决定的:
x:5:respawn:/etc/X11/prefdm -nodaemon
7. 启动过程中会用到的主要配置文件
/sbin/init
的运行过程中有许多执行脚本, 包括/etc/rc.d/rc.sysinit
以及/etc/rc.d/rc
等, 这些脚本都会使用到相当多的系统配置文件, 这些启动过程中的配置文件大多放在/etc/sysconfig/
目录下, 同时, 由于内核还需要加在一些驱动程序(内核模块), 此时系统自定义的设备与模块对应文件(/etc/modprobe.conf
)就显得相当重要了
-
关于模块:
/etc/modprobe.conf
某些条件下我们还是得对模块进行一些参数的规划, 此时就得用到
/etc/modprobe.conf
cat /etc/modprobe.conf
alias eth0 8139too #让eth0使用8139too的模块
alias scsi_hostadapter pata_sis
options snd-card-0 index=0 #额外指定snd-card-0的参数功能
options snd-trident index=0
这个文件大多在于制定系统内硬件所使用的模块, 这个文件通常是系统自行产生的, 一般不需要手动处理, 不过如果系统检测到错误的驱动程序, 或者你想要使用更新的驱动程序来对应相关的硬件设备时, 就要自行手动处理一下这个文件了
-
/etc/sysconfig/*
, 总而言之, 这个文件很重要, 启动过程中经常会被读取到-
authconfig
主要设置用户的身份认证的机制, 包括是否使用本机的
/etc/passwd, /etc/shadow
等, 以及/etc/shadow
密码记录使用何种加密算法, 还有是否使用外部密码服务器提供的账号验证(NIS, LDAP)等, 系统默认使用md5加密算法, 并且不使用外部的身份验证机制 -
clock
用于设置Linux主机的时区, 在clock文件内的设置选项“ZONE”所参考的时区位于
/usr/share/zoneinfo/
目录下的相对路径中, 而且要修改时区的话, 还得将/usr/share/zoneinfo/Asia/Shanghai
这个文件复制成为/etc/localtime
才行 -
i18n
用于设置一些语系的使用方面
-
keyboard & mouse
设置键盘与鼠标的形式
-
network
设置是否要启动网络, 以及设置主机名还有网关
-
network-scripts/
主要用于设置网卡
-
8. Run level的切换
与runlevel有关的启动其实是在/etc/rc.d/rc.sysinit
执行完毕之后
#如何知道当前的runlevel?
runlevel
N 5 #左边带前一个runlevel, 右边代表目前的runlevel, 若之前没有切换过, 则前一个不存在(N)
#将目前的runlevel切换为3(注意: tty7的数据会消失)
init 3
内核与内核模块
内核一般都是压缩文件, 因此在内核使用之前, 就得要将它解压后才能加载到内存当中
目前内核都是具有可读取模块化驱动程序的功能, 即所谓的“modules(模块化)”功能, 所谓的模块化可以将它想象成是一个“插件” (插件: 可以增加或增强软件功能的辅助性程序)
内核与内核模块放在哪里呢?
- 内核:
/boot/vmlinuz
或/boot/vmlinuz-version
- 内核解压缩所需的RAMDisk:
/boot/initrd (/boot/initrd-version)
- 内核模块:
/lib/modules/version/kernel
或/lib/modules/$(uname -r)/kernel
- 内核源码:
/usr/src/linux/
或/usr/src/kernels/
(要安装才会有! 默认不安装) - 内核版本:
/proc/version
- 系统内核功能:
/proc/sys/kernel/
问题来了: 如果我有个新硬件, 偏偏我的操作系统不支持, 该怎么办?
- 1.重新编译内核, 并加入最新的硬件驱动程序源码
- 2.将该硬件的驱动程序编译成模块, 在启动时加载该模块
如果想要加载一个已存在的模块时, 该如何是好?
1. 内核模块与依赖性
要处理内核模块, 首先要了解内核提供的模块之间的相关性
/lib/modules/$(uname -r)/kernel/中, 还分为几个目录:
arch #与硬件平台有关的选项, 例如CPU的等级等
crypto #内核所支持的加密技术, 例如md5或者des等
drivers #一些硬件的驱动程序, 例如显卡, 网卡, PCI相关硬件等
fs #内核所支持的文件系统, 如vfat, reiserfs, nfs等
lib #一些函数库
net #与网络有关的各项协议数据, 还有防火墙模块(net/ipv4/netfilter/*)等
sound #与音效有关的各项模块
如果我们要一个个检查这些模块的主要信息, 然后定义出它们的依赖性, 我们可能会疯掉, linu已经提供一些模块依赖性的解决方案, 那就是检查/lib/modules/$(uname -r)/kernel/modules.dep
这个文件, 它记录了内核支持的模块的各项依赖性
#那么这个文件如何创建呢? depmod - program to generate modules.dep and map.files
depmod [-Ane]
-A : --quick, 不加任何参数时, depmod会主动分析目前内核的模块, 并且重新写入/lib/modules/$(uname -r)/kernel/modules.dep当中, 若加入-A选项, 则depmod会查找比modules.dep内还新的模块, 如果真找到新模块, 才会更新
-n : --dry-run, 不写入modules.dep, 而是将结果输出到屏幕上
-e : --errsyms, 显示出目前已加载的不可执行的模块名称
#实例: 若我做好一个网卡驱动程序, 文件名为a.ko, 该如何更新内核依赖性?
cp a.ko /lib/modules/$(uname -r)/kernel/drivers/net
depmod
#注: 内核模块扩张名一定是 .ko 结尾的
2. 内核模块的查看
#查看目前系统加载了多少模块以及模块间的依赖关系?
lsmod - program to show the status of modules in the linux kernel
Module Size Used by
模块名称 模块的大小 此模块是否被其他模块所使用
autofs4 27000 3
target_core_file 9174 0
target_core_iblock,target_core_file,target_core_pscsi
configfs 29378 2 target_core_mod
#如何查看每个模块的详细信息或者自己的模块信息?
modinfo - program to show infotmation about a linux kernel module
modinfo [module_name|filename]
3. 内核模块的加载与删除
#modprobe会主动去查找modules.dep的内容, 先克服模块的依赖性之后, 再决定需要加载的模块有哪些
modprobe [-lcfr] module_name
-l : 列出目前在/lib/modules/$(uname -r)/kernel/中的所有模块的完整文件名
-c : 列出目前系统的所有模块(更详细的代号对应表), 类似/etc/modprobe.conf
* -f : 强制加载该模块
* -r : 删除某个模块
#实例1: 加载cifs模块
modprobe cifs #不需要完整的模块文件名, 因为完整的模块文件名已记录到/lib/modules/$(uname -r)/modules.dep这个文件中, 若要删除, 执行如下命令:
modprobe -r cifs
#实例2: 加载vfat这个模块, 并查看该模块的相关模块是哪个?
modprobe vfat
lsmod | grep vfat
modprobe -r vfat
4. 内核模块的额外参数设置: /etc/modprobe.conf
假设我的网卡eth0使用ne, 但是eth1同样也使用ne, 为了避免同一个模块导致网卡的错乱, 因此先找到eth0与eth1的I/O与IRQ, 假设:
- eth0: I/O (0x300)且IRQ=5
- eth1: I/O (0x320)且IRQ=7
#则:
vi /etc/modprobe.conf
alias eth0 ne
alias eth1 ne
options eth0 io=0x300 irq=5
options eth1 io=0x320 irq=7
#如此一来, linux就不会捕获错网卡的对应了, 因为已经强制指定某个I/O了
Boot Loader: Grub
1. boot loader的两个stage
-
Stage1: 执行boot loader主程序
主程序必须要被安装在启动区, 即MBR或boot sector(但因为MBR时整个硬盘的第一个sector内的一个块, 整个大小也才446bytes), 故MBR或boot sector通常仅安装boot loader的最小主程序, 不安装相关配置文件
-
Stage2: 主程序加载配置文件
第二阶段为通过boot loader加载所有配置文件与相关的环境参数文件(包括文件系统定义与主要配置文件menu.lst), 配置文件都放在/boot/grub下
ls -l /boot/grub
-rw-r--r--. 1 root root 45 Sep 11 09:46 device.map #grub的设备对应文件
-rw-r--r--. 1 root root 63 Jul 4 15:49 device.map.backup
-rw-r--r--. 1 root root 13428 Sep 11 09:46 e2fs_stage1_5 #ext2/3文件系统的定义文件
-rw-r--r--. 1 root root 12636 Sep 11 09:46 fat_stage1_5
-rw-r--r--. 1 root root 11780 Sep 11 09:46 ffs_stage1_5
-rw-------. 1 root root 1717 Sep 11 16:55 grub.conf #grub在Red Hat中的配置文件
-rw-r--r--. 1 root root 11772 Sep 11 09:46 iso9660_stage1_5
-rw-r--r--. 1 root root 13284 Sep 11 09:46 jfs_stage1_5
lrwxrwxrwx. 1 root root 11 Jul 4 15:49 menu.lst -> ./grub.conf #此文件很重要!!!
-rw-r--r--. 1 root root 11972 Sep 11 09:46 minix_stage1_5
-rw-r--r--. 1 root root 14428 Sep 11 09:46 reiserfs_stage1_5
-rw-r--r--. 1 root root 1341 May 7 2010 splash.xpm.gz #启动时在grub下的后台图示
-rw-r--r--. 1 root root 512 Sep 11 09:46 stage1 #stage1的相关说明
-rw-r--r--. 1 root root 126148 Sep 11 09:46 stage2 #stage2的相关说明
-rw-r--r--. 1 root root 12040 Sep 11 09:46 ufs2_stage1_5
-rw-r--r--. 1 root root 11380 Sep 11 09:46 vstafs_stage1_5
-rw-r--r--. 1 root root 13980 Sep 11 09:46 xfs_stage1_5
我们的loader读取了这种文件系统定义数据后, 就能认识文件系统并读取该文件系统的内核文件
2. grub的配置文件/boot/grub/menu.lst与菜单类型
grub的优点:
- 1.认识和支持较多的文件系统
- 2.启动时可以自行编辑和修改设置选项
- 3.动态查找配置文件, 而不需要在修改配置文件后重新安装grub, 我们只要修改
/boot/grub/menu.lst
里头的设置, 下次启动后就生效了
硬盘与分区在grub中的代号
- grub到底是如何认识硬盘呢? 它对硬盘的识别使用如下代号:
- (hd0,0)
- 1.硬盘代号以小括号( )括起来
- 2.任何硬盘均以hd表示, 后面接一组数字
- 3.以“查找顺序”作为硬盘的编号, 而不是硬盘扁平电缆的排序(这个重要!)
- 4.第一个查找的硬盘为0, 第二个为1, 以此类推
- 5.每块硬盘的第一个分区为0, 依序类推
硬盘查找顺序 | 在Grub当中的代号 |
---|---|
第一块 | (hd0), (hd0,0), (hd0,1), (hd0,4) ... |
第二块 | (hd1), (hd1,0), (hd1,1), (hd1,4) ... |
-
/boot/grub/menu.lst
配置文件
vi /boot/grub/menu.lst
#先是整体设置:
[password --md5 经grub-md5-crypt加密后的密文] #password放在此处不会被破解
default=0 #默认启动选项, 使用第一个菜单启动
timeout=5 #若5秒内未动键盘, 使用默认菜单启动
splashimage=(hd0,0)/grub/splash.xpm.gz #后台图示所在的文件
hiddenmenu #读秒期间是否显示出完整的菜单界面(默认隐藏)
#直接指定内核启动
title Red Hat Enterprise Linux 6 (2.6.32-642.el6.x86_64)
[lock] #多了死锁的功能
[password --md5 经grub-md5-crypt加密后的密文] #password放在此处可以被破解
[rootnoverify (hd0,0)] #不检验此分区
root (hd0,0) #代表内核文件放在哪个分区, 而不是根目录
[hide (hd0,4)] #隐藏(hd0,4)这个分区
[makeactive] #设置此分区为活动的(active)
[chainloader +1] #利用chainloader的方式转交控制权
kernel /vmlinuz-2.6.32-642.el6.x86_64 ro root=/dev/mapper/vg_linuxofalex-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_LVM_LV=vg_linuxofalex/lv_root rd_NO_MD rd_LVM_LV=vg_linuxofalex/lv_swap SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb vga=790 [single|1]
#kernel后接的是内核的文件名, 而文件名后接的是内核的参数
#由于启动过程中要挂载根目录, 因此kernel后面接的那个root=/dev/mapper/vg_linuxofalex-lv_root指的是linux的根目录在哪个分区, 可以使用LABEL来挂载根目录
#至于rhgb为色彩显示而quiet则是安静模式(屏幕不会输出内核监测信息)
initrd /initramfs-2.6.32-642.el6.x86_64.img
#initrd: 就是前面提到的initrd制作出的RAM Disk的文件名
#实例1: 我的系统分区是/dev/hda1(/), /dev/hd2(swap), 且我的内核文件为/boot/vmlinuz, 请问grub的menu.lst内该如何编写内核文件位置?
title Linux $(uname -r)
root (hd0,0)
kernel (hd0,0)/boot/vmlinuz ro root=/dev/hda1/ rhgb quiet #root=LABEL=/1
initrd (hd0,0)/boot/initrd.$(uname -r)
#注: 此处的/boot为(hd0,0)内根目录下的一个目录
#实例2: 同上, 只是我的分区情况变成了/dev/sda1(/boot), /dev/sda5(/)时呢?
title Linux $(uname -r)
root (hd0,0)
kernel (hd0,0)/vmlinuz
initrd (hd0,0)/initrd.$(uname -r)
#注: 此处的/boot为在(hd0,0)内独立的一个分区
#如何重新读取MBR内的配置文件?
title Linux $(uname -r)
root (hd0) #MBR为整块磁盘的第一个扇区, 故用整块磁盘的代号
...
3. initrd的重要性与创建新的initrd文件
initrd的目的: 提供启动过程中最需要的内核模块
需要initrd的时刻:
- 1.根目录所在的磁盘为SATA, SCSI, USB等特殊接口
- 2.根目录所在文件系统为LVM, RAID等特殊格式
- 3.根目录所在的文件系统为非传统linux“认识”的文件系统
- 4.其他必须在内核加载时提供的模块
#如果你有特殊需求而想重置initrd文件的话?
mkinitrd [-v] [--with=新加入的模块名称] init文件名 内核版本
-v : 显示mkinitrd的运行过程
--with=新加入的模块名称 : 模块名称指的是模块的名字而已, 不需要填写绝对路径的文件名, 例如: 目前内核版本的ext3文件系统模块下的文件名: /lib/modules/$(uname -r)/kernel/fs/ext3/ext3.ko 那你只要写成"--with=ext3"就好了, (省略.ko)
initrd文件名 : 你所需要创建的initrd文件的文件名
内核版本 : 某一个内核版本, 若是目前的内核版本则是"$(uname -r)"
#实例: 以mkinitrd的默认功能创建一个initrd的虚拟文件系统
mkinitrd -v initrd_$(uname -r) $(uname -r)
#实例二: 增加8139too这个模块的initrd文件
mkinitrd -v --with=8139too initrd_$(uname -r) $(uname -r)
initrd创建完成之后, 同时内核也处理完毕, 我们就可以使用grub新建菜单了
4. 测试与安装grub
若你的linux原来使用的并非grub, 现再你希望使用grub, 该如何安装它呢?
1. 利用grub-install安装配置文件
grub-install [--root-directory=DIR] INSTALL_DEVICE
--root-directory=DIR : 那个DIR为实际的绝对路劲目录, 使用grub-install默认将grub的所有文件都复制到/boot/grub/内, 如果想要复制到其他目录与设备中, 就需要指定
INSTALL_DEVICE : 安装的设备代号
#实例1: 将grub安装在目录系统的MBR下, 我的系统为/dev/sda
grub-install /dev/sda #默认安装路径/boot/grub下的所有目录的时间会被更新, 因为我们重装了
#实例2: 我的/home为独立的/dev/sdb3, 如何安装grub到/dev/sdb3 (boot sector)
grub-install --root-directory=/home /dev/sdb3
#会自动帮你生成/boot/grub/目录与文件, 但是要注意, 我们没有menu.lst这个配置文件, 这个文件需要自己手动创建
2. 将grub主程序安装到boot sector或MBR
想要将grub的主程序再次安装到/dev/sdb1的boot sector或MBR上, 需要使用grub shell
- 1.用
root (hdx,x)
c选择含有grub目录的那个分区代号 - 2.用
find /boot/grub/stage1
看看能否找到那个安装信息文件 - 3.用
find /boot/vmlinuz
看看能否在到内核文件(不一定要成功) - 4.用
setup (hdx,x)
或setup (hdx)
将grub安装到boot sector或MBR中 - 5.用
quit
离开grub shell
grub #进入grub shell
#1. 先设置一下那个含有grub目录的那个分区
grub>root (hd0,0)
Filesystem type is ext2fs, partition type 0x83 #此处可以发现grub能够识别文件系统
#2. 查找一下是否存在stage1这个配置文件
grub>find /boot/grub/stage1
(hd0,2)
#怎么会只有一个, 我们明明有/boot/grub/与/home/boot/grub/啊?
#因为/boot是独立的, 因此找到该文件就得用一下的方式:
grub>find /grub/stage1
(hd0,0)
#要特别注意grub找到的不是目录树, 而是设备内的文件
#3. 查找是否可以找到内核文件/boot/vmlinuz-2.6.18-92.el5 (非必要)
grub>find /boot/vmlinuz-2.6.18-92.el5
Error 15: File not found
grub>find /vmlinuz-2.6.18-92.el5
(hd0,0)
#4. 将主程序安装到MBR
grub>setup (hd0)
#5. 重复安装到/dev/sda1的boot sector中
grub>setup (hd0,0)
grub>quit
启动过程的问题解决
1. init配置文件错误
单用户模式唯一无法挽救的情况: /etc/inittab这个文件设置错误导致无法启动
因为single mode(runlevel 1)也是要读取/etc/inittab来进行开机的
既然默认的init无法执行, 就告诉内核不要执行init, 改用bash, 在启动进入grub后, 在grub edit下这样做:
grubedit> kernel /vmlinuz-2.6.18-92.el15 ro root=LABEL=/1 rhgb quiet init=/bin/bash
2. BIOS磁盘对应问题
我可否将Windows安装在/dev/sda中而Linux安装在/dev/sdb中, 然后调整BIOS的启动设备顺序, 如此两套系统都安装在各自的MBR中, 这样做非常好, 问题是: grub对磁盘的设备代号使用的是检测到的顺序! 也就是说, 你调整了BIOS磁盘的启动顺序后, 你的menu.lst可能对应到了错误的磁盘上
我们可以通过/boot/grub/device.map
这个文件来写死每个设备对grub磁盘代号的对应关系
cat /boot/grub/device.map
(fd0) /dev/fd0
(hd0) /dev/sda
如果你不清楚如何处理的话, 也可以利用grub-install
的功能
grub-install --recheck /dev/sdb1 #这样device.map就会主动更新了
3. 因为文件系统错误而无法启动
- 最容易出错的设置而导致无法顺利启动的步骤通常是
/etc/fstab
这个文件, 尤其是用户在实践quota时, 最容易写错参数, 又没有经过mount -a
来测试挂载, 就立刻启动, 就会出现问题 - 除了
/etc/fstab
编辑错误, 如果你曾经不正常关机, 也可能导致文件系统不一致(inconsistent), 也有可能会出现相同的问题, 此时你就应该用fsck
检测对应出错的磁盘或分区, 等到系统发现错误, 并出现clear[Y/N]
后, 输入Y
4. 利用chroot切换到另一块硬盘工作
chroot - change root directory
, 这个命令可以暂时将根目录移到某个目录下, 然后去处理某个问题, 最后再离开该root而回到原本的系统中
chroot更换根目录时要注意以下几点:
1.更换后的目录要有对应的shell
2.要有对应shell的库文件
例: ldd $(which bash)
, 其中库目录的名称也需要注意,lib或lib64
-
3.其他命令在执行时同样有库的依赖关系
本文基于<鸟哥的Linux私房菜>, 归纳整理, 在此致谢鸟哥.