Linux开机流程
Linux执行的时候,虽然没有任何画面,但其实有很多的程序在背景底下执行的,例如登录文件程控程序,例行性工作安排,还有一大堆网络服务,邮件服务器,www服务器
如果不正常关机将会导致伤害硬盘及数据传输的动作
开机中用到的那个开机管理程序(Boot Loader)使用的软件可能不一样,大多数的Linux distributions使用的是grub,早期的LILO,spfdisk
系统开机的大致经过:
1 加载BIOS的硬件信息与进行自我测试,并依据设定取得第一个可开机的装置(BIOS程序加载CMOS的信息,并根据CMOS内的设定值取得主机的各项硬件配置)
2 读取并执行第一个开机装置内MBR的boot Loader(也就是grub, spfdisk等程序)(由于不同的操作系统的文件格式不同,此时需要有一个开机管理程序处理核心加载的问题)
3 依据boot loader的设定加载kernel,kernel会开始侦测硬件与加载驱动程序(BIOS是通过硬件的INT13功能读取磁盘的第一个扇区内的MBR,这样boot loader就能被执行)
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程序 最后等待用户登入
BootLoader的功能
Loader的功能是要认识操作系统的文件格式并加载核心到主存储器中去执行,由于不同操作系统的文件格式不一致,因此每种操作系统都有自己的boot loader,loader才有办法
载入核心档案,那系统只有一个MBR,如何安装多个操作系统呢?其实每个文件系统都会保留一块启动扇区提供操作系统安装boot loader ,而通常操作系统默认都会安装一份
loader到根目录所在的文件系统的boot sector上
每个操作系统默认会安装一套boot loader到他自己的文件系统中(每个filesystem左下角的方框),linux系统安装时,你可以选择boot loader安装到MBR去,也可以选择不安装
如果选择安装到MBR的话,那理论上你在MBR与boot sector都会保有一份boot loader,这样操作系统可以透过自己的boot loader来加载核心,问题是系统的MBR只有一个
怎么才能执行boot sector中boot loader呢?
提供选单:用户可以选择不同的开机项目,这也是多重引导的重要功能!
载入核心档案:直接指向可开机的程序区段来开始操作系统;
转交其他 loader:将开机管理功能转交给其他 loader 负责。
由于具有选单功能,我们可以选择不同的核心来开机,由于具有控制权转交的功能,因此我们可以加载其他boot sector内的loader,不过Windows的loader不具有控制权转交
的功能,因此不能使用windows的loader来加载linux的loader
我们MBR使用Linux的grub这个开机管理程序,里面有三个选单,第一个直接指向Linux的核心档案并且直接加载核心来开机,第二个可以将管理权交给windows来管理
此时windows的load会接管开机流程,第三个使用linux在boot sector内的开机管理程序,此时会跳出另一个grub的选单啦,最终boot loader的功能就是加载kernel档案
加载后将核心解压缩到主存储器中,并且利用核心的功能,开始测试与驱动各个周边装置,包括储存装置,CPU,网络卡,等等,linux核心重新侦测一次硬件,而不一定
使用BIOS侦测到的硬件信息,此时核心开机接管BIOS的工作,核心档案被放置到/boot里面,取名为/boot/vmlinuz
ls --format=single-column -F /boot
config-2.6.18-92.el5 <==此版本核心被编译时选择的功能与模块配置文件
grub/ <==就是开机管理程序 grub 相关数据目录
initrd-2.6.18-92.el5.img <==虚拟文件系统档!
System.map-2.6.18-92.el5 <==核心功能放置到内存地址的对应表
vmlinuz-2.6.18-92.el5 <==就是核心档案啦!最重要者!
Linux核心是可以透过动态加载核心模块(相当于驱动程序),这些核心模块放置在/lib/modules/目录内,/lib与/ 一定要在一个文件系统中,不能放在不同partition,因此开机时
核心必须要挂载根目录,这样才能够读取核心模块提供加载驱动程序的功能,为了担心影响到磁盘内的文件系统,因此开机过程中目录是以只读的方式来挂载的
一般来说,非必要的功能可以编译成为模块的核心功能,Linux distribution都会将他编译成为模块,因此USB,SATA SCSI等磁盘装置的驱动程序通常都是以模块的方式来存在的
假设linux安装在SATA磁盘上面,通过BIOS的INT13取得boot loader 与kernel,接着kernel尝试挂载根目录来取得额外的驱动程序,由于核心不认识SATA磁盘,所以需要驱动
程序,而驱动程序则是在/lib/modules内,根本无法挂载根目录,也就无法取得/lib/modules/ 内的驱动程序,这种情况下,可以通过虚拟文件系统来处理这个问题
虚拟文件系统 (Initial RAM Disk) 一般使用的档名为 /boot/initrd,这个档案的特色是,他也能够透过 boot loader 来加载到内存中,然后这个档案会被觋压缩幵丏在内存
当中仿真成一个根目录, 且此仿真在内存当中的文件系统提供一支可执行的程序,透过该程序来加载开机过程中所需要的核心模块,通常这些模块就是USB,RAID,LVM,SCSI
等文件系统与磁盘接口的驱动程序,等载入完成后,会帮助核心重新呼叫/sbin/init 来开始后续的正常开机流程.
boot loader 可以加载 kernel 不 initrd,然后在内存中让 initrd 解压缩成为根目录,kernel 就能够藉此加载适当的驱劢程序,最终释放虚拟文件系统,幵挂载实际的根目录文件
系统
initrd档案的内容:
file initramfs-2.6.32-279.el6.x86_64.img 查看到原来是gzip的压缩文件,因为是gzip,
所以扩展名改为.gz mv initrd-2.6.18-92.el5.img initrd-2.6.18-92.el5.gz
接着解压缩 gzip -d initrd-2.6.18-92.el5.gz
再次查看文件类型 file initramfs-2.6.32-279.el6.x86_64 原来是cpio的指令压缩成的档案
再次解压缩 cpio -ivcdu < initrd-2.6.18-92.el5
可以看出这个文件中的内容和根目录很像,尤其也是有init这个执行档,查看init执行档中的档案内容
cat init
mount -t proc /proc /proc <==挂载内存的虚拟文件系统
mknod /dev/null c 1 3 <==建立系统所需要的各项装置!
insmod /lib/ehci-hcd.ko <==加载各项核心模块,就是驱动程序!
mkrootdev -t ext3 -o defaults,ro hdc2 <==尝试挂载根目录!
由上面的内容我们知道initrd有加载模块并且尝试挂载了虚拟文件系统,接下来能够顺利的运作,那么是否一定需要initrd
需要initrd最重要的原因是,当开机时无法挂载根目录的情况下,此时需要initrd ,例如你的根目录在特殊的磁盘接口
USB SATA SCSI 或者是你的文件系统位特殊(LVM RAID)等等,才需要initrd,但是如果你的LInux安装在IDE接口的磁盘上
并且默认使用的是ext2或ext3文件系统,那么不需要initrd也能够顺利的开机进入Linux的
核心加载完毕, 进行完硬件侦测和驱动完整的加载后,接下来开始执行系统的第一支程序 /sbin/init,init的PID号码是一号
/sbin/init 最主要的功能就是准备软件执行的环境,包括系统的主机名,网络设定,语系处理,文件系统格式以及其他服务的
启动,而所有的动作都会透过init的配置文件,也就是/etc/inittab来规划,而inittab还有一个重要的设定,就是默认的runlevel
(开机执行等级)
id:5:initdefault: <==预设的 runlevel 设定, 此 runlevel 为 5
si::sysinit:/etc/rc.d/rc.sysinit <==准备系统软件执行的环境的脚本执行档
l0:0:wait:/etc/rc.d/rc 0 <==runlevel 0 在 /etc/rc.d/rc0.d/
l1:1:wait:/etc/rc.d/rc 1 <==runlevel 1 在 /etc/rc.d/rc1.d/
l2:2:wait:/etc/rc.d/rc 2 <==runlevel 2 在 /etc/rc.d/rc2.d/
l3:3:wait:/etc/rc.d/rc 3 <==runlevel 3 在 /etc/rc.d/rc3.d/
l4:4:wait:/etc/rc.d/rc 4 <==runlevel 4 在 /etc/rc.d/rc4.d/
l5:5:wait:/etc/rc.d/rc 5 <==runlevel 5 在 /etc/rc.d/rc5.d/
l6:6:wait:/etc/rc.d/rc 6 <==runlevel 6 在 /etc/rc.d/rc6.d/
是否允许按下 [ctrl]+[alt]+[del] 就重新启动的设定项目: ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# 底下两个讴定则是关亍丌断电系统的 (UPS),一个是没电力时的关机,一个是复电的处理
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
1:2345:respawn:/sbin/mingetty tty1 <==其实 tty1~tty6 是由底下这六行决定的
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:5:respawn:/etc/X11/prefdm -nodaemon <==X window 则是这行决定的!
init 的动作项目:主要可以进行的动作项目意义有:
initdefault 代表预设的 run level 设定值
sysinit 代表系统初始化的动作项目
ctrlaltdel 代表 [ctrl]+[alt]+[del] 三个按键是否可以重新启动的设定
wait 代表后面字段设定的指令项目必须要执行完毕才能继续底下其他的动作
respawn 代表后面字段的指令可以无限制的再生 (重新启动)
举例来说, tty1 的 mingetty产生的可登入画面,在你注销而结束后,系统会再开一个新的可登入画面等待下一个登入
init的作用
1. 先取得 runlevel 亦即默认执行等级的相关等级 通常预设都是 3 或 5来作为预设的run level的,但有时需要进入run level 1,也就是单人维护模式
2. 使用 /etc/rc.d/rc.sysinit 进行系统环境初始化
3. 由亍 runlevel 是 5 ,因此只进行『l5:5:wait:/etc/rc.d/rc 5』,其他行则略过
4. 设定好 [ctrl]+[alt]+[del] 这组的组合键功能
5. 设定不断电系统的 pf, pr 两种机制;
6. 启动 mingetty 的六个终端机 (tty1 ~ tty6) 如果不想要启动六个终端机,那么可以将 6:2345:respawn:/sbin/mingettytty6』关闭数个。但务必至少激活一个
7. 最终以 /etc/X11/perfdm -nodaemon 启动图形接口啦!
在init 取得run level后,接下来处理系统初始化流程 /etc/rc.d/rc.sysinit 表示在加载各项系统服务之前,得先做好整个系统环境,主要利用/etc/rc.d/rc.sysinit
这个shell script来设定好我的系统环境,接着描述sysinit主要的工作项目:
1 取得网络环境不主机类型: 读取/etc/sysconfig/network 等网络环境设置
2 测试与挂载内存装置/proc 以及一些USB装置 /sys
3 决定是否启动 SELinux
4 启动系统的随机数生成器 随机数生成器可以帮助系统进行一些密码加密演算的功能,在此需要启动两次随机数生成器
5 设定终端机字形
6 设定显示亍开机过程中的欢迎画面 (text banner);
7 设定系统时间 (clock) 与时区设定:需读入 /etc/sysconfig/clock 设定值
8 接口设备的侦测与 Plug and Play (PnP) 参数的测试:根据核心在开机时侦测的结果 (/proc/sys/kernel/modprobe ) 开始进行 ide / scsi / 网络 / 音效等接口设备的侦测,
以及利用以加载的核心模块进行 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 档案中
rc.sysinit将基本的系统设定数据都写好了,也将系统的数据设定完整,如果想了解开机过程发生了什么,执行dmesg把,在这个档案中所进行的
很多预设配置文件,其实都是在/etc/sysconfig/当中
如果想要加载核心模块的话,可以将模块写入到/etc/sysconfig/module/*.modules当中,只要记得以.modules结尾即可,其实目前的默认模块
已经够用了,除非你的主机硬件实在太新了,非要自己加载新的模块不可,否则在经过rc.sysinit处理后,你的主机应该可以跑得很顺畅了
接着就等着你将系统相关的服务与网络服务启动
run level要执行的各项脚本放置处是 /etc/rc.d/目录下,主要是够过/etc/rc.d/rc这个指令来处理相关任务,如果预设是5的话,那么就取对应的rc 5这个目录
我们先看/etc/rc.d/rc这个档案
透过外部第一号参数($1)来取得想要执行的脚本目录,也就是指/etc/rc.d/rc 5,可以取得/etc/rc5.d/这个目录来准备处理相关的脚本程序
找到 /etc/rc5.d/K??* 开头的档案 并进行/etc/rc5.d/K??* stop
找到 /etc/rc5.d/S??* 开头的档案 并进行/etc/rc5.d/S??* start
查看rc5.d/这个目录的内容,这个目录下的所有档案都是以Sxx或Kxx 全部都是连结档,链接到stand alone服务启动的目录/etc/init.d/去
可以看出 /etc/rc5.d/[SK]xx 就是/etc/init.d目录下去找对应的服务脚本,然后分别进行start和stop的动作而已
例如表格内的 K91capi 及 S10network 为例好了,透过/etc/rc.d/rc 5的执行
/etc/rc5.d/K91capi stop --> /etc/init.d/capi stop
/etc/rc5.d/S10network start --> /etc/init.d/network start
所以想要启动该runlevel时就启动执行的服务,那么利用Sxx指向/etc/init.d/的特定服务启动脚本后,该服务就能够在开机时启动了,chkconfig就是负责
处理这个链接档的命令,那么K与S后面的数字表示各个不同的服务其实还是互有关系的,例如想要启动WWW服务,总要有网络,所以/etc/init.d/network就
必须先要被启动啦,现在应该有点了解S或者K后面数字的意思了吧,那就是执行的顺序,看看哪个是最后一个被执行的项目呢,其实是S99local,也就是/etc/rc.d/rc.local档案
用于自定义开机启动程序/etc/rc.d/rc.local
例如在完成预设runlevel指定的各项服务的启动后,还有一些其他的动作想要完成,例如给某人寄一份信,通知他,启动完毕,那就不需要再制作一个
shell script 放置在/etc/init.d/里面,通过连接方式链接到/etc/rc5.d/里面,可以将执行的命令放在/etc/rc.d/rc.local文件中,所以可以把自己制作的并且需要
在开机时启动的脚本完整档名写入/etc/rc.d/rc.local,如此一来,开机就会将我的shell script 执行过
加载终端机或X-Window接口
在完成了所有服务的启动后,接下来Linux就会启动终端机或者X window来等待使用者登入
run level 2,3,4,5时,都会执行/sbin/mingetty这个咚咚,而且执行六个,也就是Linux会提供六个纯文本终端机,因为mingetty就是启动终端机的指令
要注意的是那个 respawn 的 init 动作项目,他代表当后面的指令被终止时,init会主动重新启动该项目,也就是登入tty1终端机接口后,以exit离开后
系统还会重新显示等待用户输入的画面,如果改天不想要六个终端机,可以取消某些终端机接口,将不需要的终端的那行信息给批注掉,下次重新启动
后,你的Linux就不会显示那几个终端了,除了终端机之外,init还会执行/etc/X11/prefdm-nodaemon那个指令,他主要就是启动X window
开机中遇到的主要配置文件 /etc/rc.d/rc.sysinit以及/etc/rc.d/rc等等, 这些脚本都会使用相当多的系统配置文件,那么系统开机会用到的配置文件大多放置
/etc/sysconfig目录下,同时,由于核心还是要加载一些驱动程序(核心模块),此时系统自定义的装置与模块对应文件/etc/modprobe.conf就很重要了
/etc/modprobe.conf档案
前面rc.sysinit档案中谈到加载用户自定义模块,就是在/etc/sysconfig/modules目录下,某些条件下我们需要对模块的一些参数进行规划,此时
我们就要使用到/etc/modprobe.conf文件
/etc/sysconfig/*下所有的几个重要档案
authconfig 这个档案主要规范使用者的身份认证的机制,包括使用本机的/etc/passwd /etc/shadow以及/etc/shadow密码记录使用何种加密算法
还有是否使用外部密码服务器提供的帐号验证(NIS LDAP)等,系统默认使用MD5加密算法,不使用外部的身份验证机制
clock 此档案设定Linux主机的时区,可以使用格林威治时间(GMT),也可以使用本地时间(local) 在clock档案内的设定项目【ZONE】所参考的
时区位于/usr/share/zoneinfo目录下的相对路径中,而且要修改时区的话,还得将/usr/share/zoneinfo/Asia/Shanghai这个档案复制成为
/etc/localtime才行.
i18n 设定语系的使用方面,更改这个i18n的档案,可以设置当前的语系环境
keyboard & mouse
keyboard与mouse就是设定键盘与鼠标的形式
network 可以设定是否需要启动网络,以及设定主机名还有网关(GATEWAY)这两个重要信息
network-scripts/ 主要用来设定网络卡
Run level 的切换 其实run level的不同仅是/etc/rc[0-6].d里面启动的服务不同而已,不过,依据开机是否自动进入不同run level 的设定
1 每次开机执行预设的run level 亦即是 id:5:initdefault里头的数字
2 如果只是暂时的变更系统的run level时,则使用init[0-6]来进行run level的变更,但下次重新启动,依旧会以/etc/initta的设定为准
如果想从 init 5 切换为init 3 不同的run level 只是加载的服务不同,亦即是/etc/rc5.d/还有/etc/rc3.d内的Sxx与Kxx有差异而已
所以切换的时候先比对/etc/rc.d/及/etc/rc5.d内的K与S开头的档案
在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 K 开头档案,则予以关闭;
在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 S 开头档案,则予以启动;
查看当前的run level ,可以在bash当中输入runlevel即可,结果显示5 3 看吧!前一个是 runlevel 5 ,目前的是 runlevel 3 啦
核心与核心模块
整个开机的过程中,能否成功的驱动我们主机的硬件配备,是核心的工作,而核心一般是压缩文件,因此使用核心之前,就要将他解压缩
才能加载主存储器中。目前为了应付日新月异的硬件,目前的核心都是具有【可读取模块化驱动程序】的功能,亦即所谓的模块化功能,所谓
的模块化可以想象成是一个插件,该插件由硬件开发商提供,也有可能我们的核心本来就支持,不过,较新的硬件,通常都需要开发商提供驱动
程序模块啦
核心与核心模块放置的位置
核心: /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
那么如果有个新的硬件,偏偏我的操作系统不支持,办法有俩个:
1 重新编译核心 并加入最新的硬件驱动程序原始码
2 将该硬件的驱动程序编译成为模块 在开机时加载该模块 牵涉到 原始码与 tarball
核心模块与相依性
既然要处理核心模块,自然就要了解我们核心提供的模块之间的相关性,核心模块放置在/lib/modules/$(uname -r)/kernel 当中
里面主要有几个目录
arch :与硬件平台有关的项目,例如 CPU 的等级等等;
crypto :核心所支持的加密的技术,例如 md5或者是 des 等等;
drivers :一些硬件的驱动程序,例如显示适配器、网络卡、PCI 相关硬件等等;
fs :核心所支持的 filesystems ,例如 vfat, reiserfs, nfs 等等;
lib :一些函数库;
net :与网络有关的各项协议数据,还有防火墙模块 (net/ipv4/netfilter/*)等等;
sound :与音效有关的各项模块;
可以通过检查/lib/modules/$(uname -r)/modules.dep 这个档案 ,他会记录了核心支持的模块的各项相依性
那么这个档案是如何建立的,很简单,是利用depmod这个指令就可以达到建立该档案的需求了
不加任何参数时,depmod会主动的去分析目前核心的模块,并且重新写入/lib/modules/$(uname -r)/modules.dep当中
-A 则depmod会去搜寻比modules.dep内还要新的模块,如果真找到新模块,才会更新
-n 不写入modules.dep 而是将结果输出到屏幕上(standard out)
-e 显示出目前已加载的不可执行的模块名称
若制作好一个网卡驱动程序,档名为a.ko 该如何更新核心相依性
cp -a.ko /lib/modules/$(uname -r)/kernel/drivers/net
接着执行depmod ,该程序会到/lib/modules/$(uname -r)/kernel , 并且依据相关目录的定义将全部的模块捉出来分析,最终将分析的结果写入
modules.dep档案中,这个档案很重要,因为他会影响到modprobe指令的应用
核心模块的观察
lsmod,使用lsmod之后,系统会显示出目前已经存在于核心当中的模块,目前的内容包括
模块名称(Module);
模块的大小(size);
此模块是否被其他模块所使用 (Used by)。
mii 9409 2 8139too,8139cp <==mii 还被 8139cp, 8139too 使用
mii这个模块会被8139too所使用 , 简单的说 【当你要加载 8139too 时,需要先加载 mii 这个模块才可以顺利的加载 8139too】
除了显示出目前的模块外,还可以查阅每个模块的信息 ,那如果想要知道mii是什么,可以用modinfo来观察的
modinfo
-a :仅列出作者名称;
-d :仅列出该 modules 的说明 (description);
-l :仅列出授权 (license);
-n :仅列出该模块的详细路径
核心模块的加载和移除
如果想要自行手动加载模块,是使用modprobe这个指令来加载模块,因为modprobe会主动的去搜寻modules.dep的内容,先客服了模块
的相依性后,才决定需要加载的模块有那些,至于insmod则完全由使用者自行加载一个完整文件名的模块,并不会主动分析模块相依性
insmod /lib/modules/$(uname -r)/kernel/fs/cifs/cifs.ko 尝试载入cifs.ko这个文件系统模块
lsmod | grep cifs 查看
rmmod cifs 将刚刚加载的cifs模块移除
-f :强制将该模块移除掉,不论是否正被使用;
-w :若该模块正被使用,则 rmmod 会等待该模块被使用完毕后,才移除他!
不过使用insmod和rmmod的问题就是, 你必须要自行找到模块的完整文件名才行,而且万一模块的相依属性有问题时,你将无法直接加载
或移除该模块,所以还是建议直接使用modprobe来处理模块加载的问题,这个指令的用法是:
-c :列出目前系统所有的模块!(更详细的代号对应表)
-l :列出目前在 /lib/modules/`uname -r`/kernel 当中的所有模块完整文件名;
-f :强制加载该模块;
-r :类似 rmmod ,就是移除某个模块
modprobe cifs 因为该完整文件名已经记录到/lib/modules/$(uname -r)/modules.dep当中的缘故
移除的话执行modprobe -r cifs
所以使用modprobe要比insmod和rmmod方便的多,因为他是主要去搜寻modules.dep的记录,所以,当然可以克服模块的相依性问题
所以还不需要知道该模块的详细路径
modprobe vfat 接着执行 lsmod | grep vfat 查看到:
vfat 15809 0
fat 51165 1 vfat <==原来就是 fat 这个模块啊!
modprobe -r vfat <==测试完移除此模块
核心模块的额外参数设定: /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就不会捉错网络卡的对应了
在经历了开机流程后,会发现boot loader 是载入核心的重要工具,没有boot loader的话 那么kernel根本就没有办法被系统加载
所以现在来谈一些boot loader的功能,Linux最主流的grub这个boot loader
boot loader 的两个stage
boot loader具有选单功能,直接加载核心档案以及控制移交的功能,系统必须要有loader才有办法加载操作系统的核心 ,但是MBR
的整个硬盘的第一个分区中的一个区块,整个大小为446bytes ,而loader功能这么强,光是程序代码与设定数据不可能只占用不到
446bytes的容量,为了解决这个问题,所以Linux将boot loader的程序代码执行与设定值加载分成两个阶段来执行
Stage 1:执行 boot loader 主程序:
第一阶段为执行 boot loader 的主程序,这个主程序必须要被安装在开机区,亦即是MBR或者是boot sector,但是因为MBR实在太小,所以
MBR或boot sector通常仅安装boot loader的最小主程序,并没有安装loader的相关配置文件
Stage 2:主程序加载配置文件:
第二阶段透过boot loader加载所有配置文件和相关的环境参数档案(包括文件系统定义与主要配置文件menu.lst)一般来说 配置文件都在/boot 底下
这些grub有关的档案都放置在/boot/grub中,其实在这个目录下最重要的就是
配置文件menu.lst以及各个文件系统的定义,我们loader读取了
文件系统定义数据后,就能够认识系统并读取在该文件系统内的核心档案,至于grub的配置文件档名,其实是menu.lst的,只是Red Hat里面
被定义为/boot/grub.conf,不过建议还是记忆menu.lst比较好
grub的配置文件/boot/grub/menu.lst与选单类型,
由于grub认识的文件系统真的非常多,所以grub才会被那么广泛使用,grub的优点包括:
1 认识与支持较多的文件系统,并且可以使用grub的主程序直接在文件系统中搜寻核心档案
2 开机的时候,可以自行编辑与修改开机设定项目 类似bash的指令模式
3 可以动他搜寻配置文件,而不需要在修改配置文件后重新安装grub,亦即我们只要修改完menu.lst 里头的设定后,下次开机就
生效了
menu.lst档案的内容
安装MBR的grub主程序,最重要的任务就是从磁盘中加载核心档案,以让核心能够顺利的驱动整个系统的硬件,所以grub必须认识
硬盘才行,那么grub如何认识硬盘呢? grub对硬盘的代号设定与传统的Linux磁盘代号可以完全的不同的,grub对硬盘的识别使用
的是如下内容
(hd0,0) 跟 /dev/hda1看上去不相干,其实是同一个东西
(hd0,0) 硬盘代号以小括号包起来,硬盘以hd表示,后面接一组数字,以【搜寻顺序】作为磁盘的编号,第一个搜寻到的硬盘为0
第二个为1号,依次类推,每颗硬盘的第一个partition代号为0 ,依次类推
所以(hd0,0)表示第一颗硬盘的第一号分割槽,反正grub里面开始的数字是0而不是1
vim /boot/grub/menu.lst
default=0 <== 默认开机选项,使用第 1 个开机选单 (title) 有几个title, 那么这个default最大为title - 1
timeout=5 <== 若5秒内未动键盘,使用默认选单开机 等待5秒,也可以设置为0代表直接使用default值进行开机而不读秒,timeout则直接进入选单,不读秒
splashimage=(hd0,0)/grub/splash.xpm.gz <==背景图示所在的档案 开机时候的背景色彩,由于这里将/boot这个目录独立成为/dev/hda1,因此hd(0,0)也是同样的含义
在/dev/hda1里面的grub/splash.xpm.gz的意思
hiddenmenu <==读秒期间是否显示出完整的选单画面(预设隐藏) ,开机的时候是否显示选单,默认不显示选单,想要显示的话,就将这行批注掉
title CentOS (2.6.18-92.el5) <==第一个选单的内容
root (hd0,0)
kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet
initrd /initrd-2.6.18-92.el5.img
title以前的四行,都是属于grub的整体设定,包括预设的等待时间与默认的开机项目,还有显示的画面特性,至于title后面才是
指定开机的核心档案或者 boot loader控制权转移到下个loader(此过程称为chain-loader),每个title后面接的是【该开机项目名称的显示】
亦即是在选单出现时,选单上面的名称而已
1 直接指定核心开机
既然要指定核心开机,所以当然要找到核心档案,此外,还要用到initrd的RAM Disk的配置文件,当尚未开机完成,所以我们必须要以grub的
磁盘识别方式找出完整的kernel与initrd档名才行.
先指定核心档案放置的partition,再读取档案(目录树), 最后才加入档案的实际文件名与路径(kernel与initrd)
由于此处 /boot 为 /dev/hda1 因此核心档案的设定则成为:
root(hd0,0) <==代表核心档案放在那个 partition 当中而不是根目录,此处根目录位/dev/hda2
kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet 由于开机过程中需要挂载根目录,因此kernel后面接的那个root=LABEL=/1值得就是
Linux根目录在那个partition的意思,这里使用LABEL转标来挂载根目录至于 rhgb 为色彩显示而 quiet 则是安静模式
initrd :就是前面提到的 initrd 制作出 RAM Disk 的档案档名啦!
也可以按以下直接指定partition与档名,不需要额外指定核心档案所在的装置代号
接着想想/boot有独立分割与无独立分割的情况
无独立分割,系统分割是/dev/hda1 (/), /dev/hda2 (swap) 核心档案为/boot/vmlinuz 那么menu.lst内容如何编写核心档案位置
kernel (hd0,0)/boot/vmlinuz root=/dev/hda1
独立分割 /dev/sda1 (/boot), /dev/sda5 (/) 那么menu.lst内容编写核心档案为
kernel (hd0,0)/vmlinuz root=/dev/hda5
2 利用chain loader 的方式转交控制权
所谓chain loader 就是将控制权交给下一个boot loader而已,所以grub不需要认识和找出kernel的档名,只要将boot的控制权交给下一个boot
sector或MBR内的boot loader而已,通常也不需要去查验下一个boot loader的文件系统
一般来说chain loader的设定只要有两个就够了,一个是预计要前往的boot sector所在的分割槽代号,另一个则是设定chainloader在那个分割槽
的boot sector(第一个扇区)上,假设windows的分割槽在 /dev/hda1,且我又只有一颗硬盘,那么要grub将控制权交给windows的loader.
vi /boot/grub/menu.lst
title Windows partition
root (hd0,0) <==设定使用此分割槽 (hd0,0)就是windows的C槽所在的磁盘,
chainloader +1 <== +1 可以想成第一个扇区,亦即是 boot sector 开机管理程序 不过windows的开机碟需要设定位活化状态
因此grub预设会去检验该分割槽的文件系统,可以将内容改写成
rootnoverify (hd0,0) <==不检验此分割槽
chainloader +1
makeactive <==设定此分割槽为开机碟(active)
还可以将运行windows期间隐藏某个分割槽需要加上 hide (hd0,4) <==隐藏 (hd0,4) 这个Linux分割槽
initrd的重要性,在于提供开机过程中所需要的重要核心模块,并且让系统开机过程可以顺利完成,模块位于/lib/modules/$(uname -r)/kernel/ 当中
各个distribution提供的核心都会附上initrd档案,但如果有特殊需要想要重置initrd档案的话,可以使用mkinitrd
mkinitrd [-v] [--with=模块名称] initrd 文件名 核心版本
-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_vbirdtest $(uname -r)
测试和安装grub
Linux主机本来就是使用grub作为loader的话,那么不需要安装grub,因为grub本来就会去主动读取配置文件,如果本来并非使用的是
grub的话,那么就需要来安装了,使用grub-install将一些必要的档案复制到/boot/grub里面去,
因为boot loader有两个stage,这个grub-install就是安装配置文件,包括文件系统定义档与menu.lst等等,如果想要将grub的stage1
主程序安装起来,就需要使用grub shell 的功能
grub-install [--root-directory=DIR] INSTALL_DEVICE
将 grub 安装在目前系统的 MBR 底下,我的系统为 /dev/hda:
我的 /home 为独立的 /dev/hda3 ,如何安装 grub 到 /dev/hda3
grub-install --root-directory=/home /dev/hda3
这样home目录下就会多出了/boot/grub/的目录
所以说grub-install是安装grub相关的档案到你的装置上面去等待在开机时被读取,但还需要设定menu.lst。再以grub shell 来安装
grub主程序到MBR或者是boot sector上面去
vim /boot/grub/menu.lst 设置三个开机选单
1. 假设 /dev/hda1 内含有 boot loader ,此 loader 如何取得控制权?
2. 如何重新读取 MBR 内的 loader ?
3. 利用你原本的系统核心档案,建立一个可强制迚入单人维护模弅的选单
1./dev/hda1 boot sector <==本例中的第一个新增选单 root (hd0,0) chainloader +1
2 title MBR loader root (hd0) <==新增的第二个选单 在<==MBR 为整颗磁盘的第一个扂区,所以用整颗磁盘的
3 title single user mode <==新增的第三个选单(其实由原本的 title 复制来的)
配置文件处理完毕,如果想要知道/dev/hda1底下到底有没有包含grub的主程序
因此我们想要将 grub 主程序再次的安装到 /dev/hda1 的 boot sector, ,也想要重新安装grub 到 MBR 上面去
此时我们就得要使用grub shell
用『 root (hdx,x) 』选择含有 grub 目录的那个 partition 代号;
用『 find /boot/grub/stage1 』看看能否找到安装信息档案;
用『 find /boot/vmlinuz 』看看能否找到 kernel file (不一定要成功!);
用『 setup (hdx,x) 』或『 setup (hdx) 』将 grub 安装在 boot sector 或 MBR;
用『 quit 』来离开 grub shell !
我们需要安装的就是那个stage1,那才是grub的主程序,而且配置文件通常与主程序摆在同一个目录下,因此我们需要使用
root(hd0,0)去找到/boot/grub/stage1,接下来,调用grub来进入grub shell 进入时会出现一个grub 的提示字符
grub
1 先设定一下含有grub目录的那个partition
root(hd0,0)
2 搜寻一下,是否存在stage1这个信息档案
grub> find /boot/grub/stage1
(hd0,2)
看到怎么只有一个,明明有/boot/grub与/home/boot/grub , 因为/boot是独立的,因此要找到该档案就得要用如下的方式
grub> find /grub/stage1
(hd0,0) 这样就能够找到了 找到的是装置内的档案,不是目录树
3 搜寻一下是否可以找到核心 /boot/vmlinuz-2.6.18-92.el5
find /vmlinuz-2.6.18-92.el5
(hd0,0) 因为/boot/是独立的,因此不需要写成 /boot/vmlinuz-2.6.18-92.el5
将主程序安装上去吧!安装到 MBR 看看!
执行setup(hd0)
那么再重复安装到我的/dev/hda1 亦即是boot sector当中
setup (hd0,0)
设置好后,接着执行quit退出grub命令
如此以来,已经将grub安装到MBR及bootsector里面去了,而且读取的是(hd0,0)里面的/grub/menu.lst那个档案
最后总结一下:
1. 如果是从其他 boot loader 转成 grub 时,得先使用 grub-install 安装 grub 配置文件;
2. 开始编辑 menu.lst 这个重要的配置文件;
3. 透过 grub 来将主程序安装到系统中,如 MBR 的 (hd0) 戒 boot sector 的 (hd0,0) 等等。
都做好后重新启动来查阅看看
由于将隐藏功能去掉了,你会直接看到这四个选单,如果按下控制权转交
e 进入grub shell的编辑画面
o 在游标所在行底下再新增一行
d 将游标所在行删除
按下【enter】,然后输入b来boot,就可以开机了,而当/boot/grub/menu.lst设定错误时,导致无法顺利开机的话,可以使用
grub的选单部分,使用grub shell的方式去查询(find)或者是直接指定核心档案,就能够开机了
那如果grub可能发生错误,导致grub都无法启动,那么根本就无法使用grub的在线编辑功能,此时可以利用具有grub开机的CD
来开机,然后再以CD的grub的在线编修,同样可以使用硬盘上面的核心档案来开机啦
关于核心功能当中的vga设定
tty1-tty6除了80*24的分辨率外,还能够有其他分辨率的支持,前提核心必须要支持FRAMEBUFFER_CONSOLE 这个核心功能选项扄行
如何确定是否支持,可以查阅/boot/config-2.6.18-92.el5 这个档案,然后这样搜寻
grep 'FRAMEBUFFER_CONSOLE' /boot/config-2.6.18-92.el5
CONFIG_FRAMEBUFFER_CONSOLE=y 结果y表示支持,而n表示不支持
那么如何调整 tty1 ~ tty6 终端机的分辨率呢 此为十进制数值
假设你想要将你的终端机屏幕分辨率调整到 1024x768 ,且颜色深度为 15bit 色的时候,就得要指定
vga=790 那个数字! 丼例来说,tty1 就想要这样的分辨率时,你可以这样做:
kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790 重新启动后,去到tty1,就已经是 1024x768 的分辨率
BIOS 无法读取大硬盘的问题 最好是重新安装,将制作出/boot这个partition,所以以后安装时,最好将/boot这个分割槽分割出来
为个别选单加上密码
首先,必须要建立密码,而且还是要加密过后的,不然别人跑到/boot/grub/menu.lst里面就能探查到你的开机密码了,我们可以
透过grub提供的md5编码处理
grub-md5-crypt
$1$kvlI0/$byrbNgkt/.REKPQdfg287. <==由$开始到.结束这就是产生的 md5 密码!将这个密码复制下来,假如我们要将第一个选项
加入这个密码,而第四个选项加入另外的密码
title CentOS (2.6.18-92.el5)
password --md5 $1$kvlI0/$byrbNgkt/.REKPQdfg287.
root (hd0,0)
kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790
initrd /initrd-2.6.18-92.el5.img
title single user mode
password --md5 $1$GFnI0/$UuiZc/7snugLtVN4J/WyM/
root (hd0,0)
kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet single
initrd /initrd-2.6.18-92.el5.img
我们两个选单进入的密码并不相同,可以进行人员的分类,此时就一定要输入密码才能进入开机流程,如果你在远程使用
reboot重新启动,并且主机前面并没有任何人的话,你的主机并不会主动进入开机程序
你必须要注意的是passwd这个项目一定要在title底下的这一行,不过,此项功能还是可能被破解,用户按e进入编辑模式
接着删除密码字段,接着重新启动开机流程,所以只好通过整体的password放在所有的title之前,然后在title底下的第一行
设定lock 那使用者想要编辑时,也需要输入密码的
vim /boot/grub/menu.lst
default=0
timeout=30
password --md5 $1$kvlI0/$byrbNgkt/.REKPQdfg287. <==放在整体设定处
splashimage=(hd0,0)/grub/splash.xpm.gz
#hiddenmenu
title CentOS (2.6.18-92.el5)
lock <==多了死锁的功能
root (hd0,0)
kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790
initrd /initrd-2.6.18-92.el5.img
重新启动后,下方出现p的功能,由于2,3,4选单没有使用lock 因此这三个选单使用者还是可以执行开机程序,而第一个
选单由于有lock项目,除非输入密码,否则第一个选单是无法被载入执行的,是具有保密menu.lst的功能
开机过程的问题解决
由于很多时候某些设定的错误,导致Linux开机无法顺利的开机成功,此时可以进入run level1单用户模式进行处理
例如忘记 root 密码的解决之道
single 参数 进入单人用户模式下,执行passwd这个指令来重建root的密码
init 配置文件错误
前一个root密码挽救的方法其实可以用在很多地方,唯一一个无法挽救的情况,那就是/etc/inittab这个档案设定错误导致无法
开机,根据开机流程,我们知道runlevel0-6 都会读取/etc/inittab配置文件,因此你使用single model(runlevel 1) 当然也是要
读取/etc/inittab来进行开机的,那既然无法进入单人维护模式,既然预设的init无法执行,那我们就告诉核心不要执行init 改
为呼叫bash ,可以略过init 同样在grub edit 的情况下这样写
grub edit> kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet init=/bin/bash
我们指定了核心呼叫的第一支程序(init)变成/bin/bash,因此/sbin/init就不会被执行,又根据开机流程的说明,我们知道此时可以
利用root取得bash来工作,此时除了根目录外,其他的目录都没有被加载,根目录被加载成为只读状态,因此我们需要手动的
将根目录重新挂载成可擦写, mount -o remount,rw / 至于mount -a 则是参考fstab的内容重新挂载文件系统,此时你又可以
进行救援的工作了,只是救援完毕后,你得要使用reboot重新启动一次才行
BIOS 磁盘对应的问题 (device.map)
如果有两个硬盘分别安装windows和linux的操作系统,接着调整BIOS的开机装置顺序,此时每颗磁盘的MBR个别有不同操作系统的
loader,问题是 grub对磁盘的装置代号使用的是侦测到的顺序,就是说,你调整BIOS磁盘开机顺序后,你的menu.lst内的装置代号
就可能会对应到错误的磁盘上了,没关系我们可以透过/boot/grub/device.map这个档案来写死每个装置对grub磁盘代号的对应
举例
cat /boot/grub/device.map
(fd0) /dev/fd0
(hd0) /dev/hda
也可以利用grub-install 的功能
grub-install --recheck /dev/hda1 这样device.map 会主动的被更新了
因文件系统错误而无法开机
最容易出错的设定通常就是/etc/fstab这个档案了,最容易写错参数,又没有经过mount -a来测试挂载,就立刻直接重新启动
看到 for type Control-D to continue); 输入root的密码来取得bash并以mount -o remount, rw /将根目录挂载可以擦写后,继续处理
造成上述画面可能的原因还有 不正常关机,如果是磁盘错乱的话 fsck告知那个出错,此时利用fsck 去检测那个装置,等到系统发现错误
并且出现clear【Y/N】输入Y吧,如果此时依然无法进入Linux,此时将系统中重要的数据复制出来,然后重新安装,并且检验一下
是否磁盘有损伤的现象,一般执行fsck就能够顺利再次进入Linux了
利用chroot切换到另一颗磁盘工作
可以暂时将根目录移动到某个目录下,然后去处理某个问题,最后再离开该root而回到换本的系统当中
例如同一个主机上面安装了两个linux系统,假设我的第一个Linux无法进入了,那么我可以使用第二个Linux开机,然后在第二个Linux系统
下将第一个Linux挂载起来,最后用chroot变换到第一个Linux,就能够进入第一个Linux的环境当中去处理工作了
同样也可以将你的Linux硬盘拔到另一个Linux主机上面去,然后用这个chroot来切换,以处理你的硬盘问题
用尽任何方法,进入一个完整的Linux系统(run level 3或5)
假设有问题的Linux磁盘在/dev/hdb1上面,且整个系统的排列是
挂载点 装置文件名
/ → /dev/hdb1
/var → /dev/hdb2
/home → /dev/hdb3
/usr → /dev/hdb5
那么在我目前的这个linux底下 我可以建立一个目录,然后这样做:
挂载点 装置文件名
/chroot/ → /dev/hdb1
/chroot/var/ → /dev/hdb2
/chroot/home/ → /dev/hdb3
/chroot/usr/ → /dev/hdb5
全部挂载完毕后,再输入 chroot /chroot 你就会发现 根目录(/) 变成那个/dev/hdb1的环境