Linux学习笔记(二十一)

来源:互联网 发布:神经网络算法代码实现 编辑:程序博客网 时间:2024/04/29 23:31

Linux的启动过程:

      1:加载BIOS的硬件信息,并获取第一个启动设备的代号。

      2:读取第一个启动设备的MBR的引导加载程序(lilo,grub,spfdisk等)的启动信息。

      3:加载核心操作系统的核心信息,可信开始解压,并且尝试驱动所有硬件设备。

      4:核心执行init程序并获取运行信息。

      5:init执行/etc/rc.d/rc.sysinit。

      6:启动核心的外挂模块(/etc/modprobe.conf)。

      7:init执行运行的各个批处理文件(scripts)。

      8:init执行/etc/rc.d/rc.local。

      9:执行/bin/login程序等待用户登录。

      10:登录之后就开始以Shell控制主机。

BIOS, 开机自我测试与 MBR 

在个人计算机架构下,你想要启动整部系统首先就得要让系统去加载 BIOS (Basic Input Output System),并透过 BIOS 程序去加载 CMOS 的信息,并且藉由 CMOS 内的设定值取得主机的各项硬件配置,在取得这些信息后,BIOS 还会进行开机自我测试 (Power-on Self Test, POST) (注1)。 然后开始执行硬件侦测的初始化,并设定 PnP 装置,之后再定义出可开机的装置顺序, 接下来就会开始进行开机装置的数据读取了 (MBR 相关的任务开始)。 

 BIOS 指定开机的装置好让我们可以读取磁盘中的操作系统核心档案。 但由于不同的操作系统他的文件系统格式不相同,因此我们必须要以一个开机管理程序来处理核心档案加载 (load) 的问题, 因此这个开机管理程序就被称为 Boot Loader 了。那这个Boot Loader 程序安装在哪里呢?就在开机装置的第一个扇区 (sector) 内,也就是我们一直谈到的MBR (Master Boot Record, 主要启动记录区)。 

加载核心侦测硬件与initrd 的功能 

当我们藉由 boot loader 的管理而开始读取核心档案后,接下来, Linux 就会将核心解压缩到主存储器当中, 并且利用核心的功能,开始测试与驱动各个周边装置,包括储存装置、CPU、网络卡、声卡等此时 Linux 核心会以自己的功能重新侦测一次硬件,而不一定会使用 BIOS 侦测到的硬件信息喔!也就是说,核心此时才开始接管 BIOS 后的工作了。一般来说,核心档案会被放置到 /boot 里面,并且取名为 /boot/vmlinuz 才对!

[root@www ~]# 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     <==就是核心档案啦!最重要者! 

虚拟文件系统 (Initial RAM Disk) 一般使用的档名为 /boot/initrd ,这个档案的特色是,他也能够透过 boot loader 来加载到内存中, 然后这个档案会被解压缩并且在内存当中仿真成一个根目录, 且此仿真在内存当中的文件系统能够提供一支可执行的程序,透过该程序来加载开机过程中所最需要的核心模块, 通常这些模块就是 USB, RAID, LVM, SCSI 等文件系统与磁盘接口的驱动程序啦!等载入完成后,会帮助核心重新呼叫 /sbin/init 来开始后续的正常开机流程。 

如上图所示,boot loader 可以加载 kernel 与 initrd ,然后在内存中让 initrd 解压缩成为根目录,kernel 就能够藉此加载适当的驱动程序,最终释放虚拟文件系统,并挂载实际的根目录文件系统, 就能够开始后续的正常开机流程。那么是否一定需要 initrd 呢? 

不见得的!需要 initrd 最重要的原因是,当开机时无法挂载根目录的情况下, 此时就一定需要 initrd ,例如你的根目录在特殊的磁盘接口 (USB, SATA, SCSI) , 或者是你的文件系统较为特殊 (LVM, RAID) 等等,就会需要 initrd。如果你的 Linux 是安装在 IDE 接口的磁盘上,并且使用默认的 ext2/ext3 文件系统, 那么不需要 initrd 也能够顺利的开机进入 Linux 的!在核心完整的加载后,您的主机应该就开始正确的运作了,接下来,就是要开始执行系统的第一支程序: /sbin/init。 

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

核心加载完以后,系统已经准备好等待程序的执行。在整个Linux系统中,第一个执行的程序就是“/sbin/init”也就是PID为1的那个。Init程序出了利用设置文件“/etc/inittab”来获取运行等级外,还会通过运行等级的设置值启动不同的服务项目。

/etc/inittab这个文件用来设置运行等级。

基本上,依据有无网络与有无 X Window 而将 run level 分为 7 个等级,分别是:

0 - halt (系统直接关机) 

1 - single user mode (单人维护模式,用在系统出问题时的维护) 

2 - Multi-user, without NFS (类似底下的 runlevel 3,但无 NFS 服务) 

3 - Full multi-user mode (完整含有网络功能的纯文字模式) 

4 - unused (系统保留功能) 

5 - X11 (与 runlevel 3 类似,但加载使用 X Window) 

6 - reboot (重新开机) 

由于 run level 0, 4, 6 不是关机、重新开机就是系统保留的,所以默认的运行等级不能设置为这3个。到底是如何取得系统的 run level 的?当然是 /etc/inittab 所设定的啰!

etc/inittab 的内容与语法

[root@www ~]# vim /etc/inittab

id:5:initdefault:                 <==预设的 runlevel 设定, 此 runlevel 为 5 

si::sysinit:/etc/rc.d/rc.sysinit  <==准备系统软件执行的环境的脚本执行档

# 7 个不同 run level 的,需要启动的服务的 scripts 放置路径:

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 则是这行决定的!

让我们解析一下这个档案吧!首先,这个档案的语法是利用冒号 (:) 将设定分隔成为四个字段,每个字段的意义与说明如下:

[设定项目]:[run level]:[init 的动作行为]:[指令项目]

设定项目:最多四个字符,代表 init 的主要工作项目,只是一个简单的代表说明。

run level:该项目在哪些 run level 底下进行的意思。如果是 35 则代表 runlevel 3 与 5 都会执行。

init 的动作项目:主要可以进行的动作项目意义有:

更多的设定项目请参考 man inittab 的说明。

指令项目:亦即应该可以进行的指令,通常是一些 script 啰。

init 的处理流程 

事实上 /etc/inittab 的设定也有点类似 shell script 啦,因为该档案内容的设定也是一行一行的从上往下处理的, 因此我们可以知道 CentOS 的 init 依据 inittab 设定的处理流程会是: 

1.  先取得 runlevel 亦即默认执行等级的相关等级 (以鸟哥的测试机为例,为 5 号); 

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) 

7.  最终以 /etc/X11/perfdm -nodaemon 启动图形接口啦! 

由于整个设定都是依据 /etc/inittab 来决定的,因此如果你想要修改任何细节的话, 可以这样做喔: 

·  如果不想让使用者利用 [crtl]+[alt]+[del] 来重新启动系统,可以将『 ca::ctrlaltdel:/sbin/shutdown -t3 -r now 』加上批注 (#) 来取消该设定 

· 规定开机的预设 run level 是纯文本的 3 号或者是具有图形接口的 5 号 ,可经由『 id:5:initdefault: 』那个数字来决定! 以鸟哥自己这个档案为例,我是使用默认的图形接口。

如果你想要关闭图形接口的话,将该行 5 改成 3 即可。 

·  如果不想要启动六个终端机 (tty1~tty6),那么可以将『 6:2345:respawn:/sbin/mingetty tty6』关闭数个。但务必至少激活一个喔!

init 处理系统初始化流程 (/etc/rc.d/rc.sysinit) 

开始加载各项系统服务之前,先做好整个系统环境,主要使用/etc/rc.d/rc.sysinit这个脚本来设置系统环境。

这个脚本的主要工作有:

1 获取网络环境与主机类型

 首先读取/etc/sysconfig/network,获取主机名与默认网关等网络环境

2 测试与载入内存设备/proc及USB设备/sys。

3 决定是否启动SELinux。

4 接口设备的检测与即插即用参数的测试。

5 用户自动以模块的加载。

6 加载核心的相关设置。

7 设置系统时间。

8 设置终端控制台字形。

9 设置RAID与LVM等硬盘功能。

10 以fsck检验磁盘文件系统。

11 进行磁盘配额quota的转化(非必要)。

12 重新以可去读模式载入系统磁盘。

13 启动quota功能。

14 启动系统随机数设备。

15 清除启动中的临时文件。

16 将启动相关信息加载到/var/log/dmesg文件中。

 这里也就将系统的数据设置完整了,使用dmesg命令就可知道在启动的时候发生了什么事情!这个文件所执行的设置文件,很多都在/etc/sysconfig这个文件夹中,可以查看这个文件夹下面的文件。

启动系统服务与相关启动设置文件(/etc/rc.d/rcn.d与/etc/sysconfig)

依据我们在 /etc/inittab 里面提到的 run level 设定值,就可以来决定启动的服务项目了。 举例来说,使用 run level 3 当然就不需要启动 X Window 的相关服务啰,您说是吧? 

那么各个不同的 run level 服务启动的各个 shell script 放在哪?还记得 /etc/inittab 里面提到的: 

l0:0:wait:/etc/rc.d/rc 0 

l1:1:wait:/etc/rc.d/rc 1 

l2:2:wait:/etc/rc.d/rc 2 

l3:3:wait:/etc/rc.d/rc 3 

l4:4:wait:/etc/rc.d/rc 4 

l5:5:wait:/etc/rc.d/rc 5  <==本例中,以此项目来解释 

l6:6:wait:/etc/rc.d/rc 6

/etc/rc.d/rc 5 的意义是这样的 (建议您自行使用 vim 去观察一下 /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 』的动作; 

[root@www ~]# ll /etc/rc5.d/ 

lrwxrwxrwx 1 root root 16 Sep  4  2008 K02dhcdbd -> ../init.d/dhcdbd 

....(中间省略).... 

lrwxrwxrwx 1 root root 14 Sep  4  2008 K91capi -> ../init.d/capi 

lrwxrwxrwx 1 root root 23 Sep  4  2008 S00microcode_ctl -

> ../init.d/microcode_ctl 

lrwxrwxrwx 1 root root 22 Sep  4  2008 S02lvm2-monitor -> ../init.d/lvm2-

monitor 

....(中间省略).... 

lrwxrwxrwx 1 root root 17 Sep  4  2008 S10network -> ../init.d/network 

....(中间省略).... 

lrwxrwxrwx 1 root root 11 Sep  4  2008 S99local -> ../rc.local 

lrwxrwxrwx 1 root root 16 Sep  4  2008 S99smartd -> ../init.d/smartd 

....(底下省略).... 

在这个目录下的档案很有趣,主要具有几个特点: 

· 档名全部以 Sxx 或 Kxx ,其中 xx 为数字,且这些数字在档案之间是有相关性的! 

·  全部是连结档,连结到 stand alone 服务启动的目录 /etc/init.d/ 去 

我们在第十八章谈过服务的启动主要是以『/etc/init.d/服务档名 {start,stop}』来启动与关闭的,那么透过刚刚 /etc/rc.d/rc 程序的解说,我们可以清楚的了解到了 /etc/rc5.d/[SK]xx 其实就是跑到/etc/init.d/ 去找到相对应的服务脚本,然后分别进行 start (Sxx) 或 stop (Kxx) 的动作而已啦!举例来说,以上述的表格内的 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 

那么为什么 后面要有数字呢?因为各不同的服务其实还是互有关系的。嘿嘿,那就是执行的顺序啦!那么哪个档案被最后执行呢? 看到最后一个被执行的项目是啥?没错,就是 S99local ,亦即是: /etc/rc.d/rc.local 这个档案啦! 

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

在启动完运行等级3之后,如果还有其它的操作要完成,举例来说,比如想邮寄一封邮件给某个系统管理员账号,那么可以在/etc/rc.d/rc.local 这个文件里面写上你想要执行的任何命令,那么你想要执行的工作在启动的时候就会自动加载咯。

根据/etc/inittab设置加载终端或X-Window界面

实际参考的项目是 /etc/inittab 内的这一段:

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:5:respawn:/etc/X11/prefdm -nodaemon

这一段代表,在 run level 2, 3, 4, 5 时,都会执行 /sbin/mingetty, 而且执行六个,这也是为何我们 Linux 会提供『六个纯文字终端机』的设定所在啊! 因为 mingetty 就是在启动终端机的指令。要注意的是那个 respawn 的 init 动作项目,他代表『当后面的指令被终止 (terminal) 时, init 会主动的重新启动该项目。』这也是为何我们登入 tty1 终端机接口后,以 exit 离开后, 系统还是会重新显示等待使用者输入的画面的原因啊!如果改天您不想要有六个终端机时,可以取消某些终端机,就将上面表格当中的某些项目批注掉即可!例如不想要 tty5 与 tty6 ,就将那两行批注, 则下次重新开机后,您的 Linux 就只剩下『 F1 ~ F4 』有效,至于如果我们使用的是 run level 5 呢?那么除了这六个终端机之外, init 还会执行 /etc/X11/prefdm -nodaemon 那个指令喔!该指令我们会在第二十四章、X Window 再来详谈! 他主要的功能就是在启动 X Window !

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

1 关于模块:/etc/modprobe.conf

2 /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/Taipei 这个档案复制成为 /etc/localtime 才行!

i18n:i18n 在设定一些语系的使用方面,例如最麻烦的文字接口下的日期显示问题! 如果你是以中文安装的,那么预设语系会被选择 zh_TW.UTF8 ,所以在纯文字接口之下, 你的档案日期显示可能就会呈现乱码!这个时候就需要更改一下这里啦!更动这个 i18n 的档案,将里面的 LC_TIME 改成 en 即可!

keyboard & mouse:keyboard 与 mouse 就是在设定键盘与鼠标的形式;

network:network 可以设定是否要启动网络,以及设定主机名称还有通讯闸 (GATEWAY) 这两个重要信息呢!

network-scripts/:至于 network-scripts 里面的档案,则是主要用在设定网络卡~ 这部份我们在服务器架设篇才会提到! 

总而言之一句话,这个目录下的档案很重要的啦!开机过程里面常常会读取到的!

变化运行等级

运行等级的不同仅仅是/etc/rc.d/rc[n].d里面启动的服务不同而已。根据启动时候自动进入不同运行等级的设置:

    要每次启动都执行某个默认的运行等级,需要修改/etc/inittab内的设置项目也就是下面这一行的内容:id:3:initdefault:

    如果只是暂时更改系统的运行等级,使用init[0~6]来更改运行等级。当然下次重新启动的时候依旧是以/etc/inittab里面的设置为准。

不同的运行等级只是加载的服务不同而已,也就是/etc/rc.d/rcA.d以及/etc/rc.d/rcB.d内的Sxxname与Kxxname的差异罢了。如果要执行从A等级到B等级的切换系统会

1:先比较/etc/rc.d/rcA.d和/etc/rc.d/rcB.d内的K与S开头的文件。

2:关闭/etc/rc.d/rcA.d内的一些服务,且该服务并不存在于/etc/rc.d/rcB.d中。

3:启动/etc/rc.d/rcB.d内的一些服务,且该服务并不存在与/etc/rc.d/rcA.d中。

也就是说,两个运行等级都存在的服务就不会被关掉。

在bash里面直接敲 “runlevel”就可以知道当前的运行等级咯。假设原本我们是以 run level 5 登入系统的,但是因为某些因素,想要切换成为 run level 3 时, 该怎么办呢?很简单啊,执行『 init 3 』即可切换。但是 init 3 这个动作到底做了什么呢? 我们不是说了吗?事实上,不同的 run level 只是加载的服务不同罢了, 亦即是 /etc/rc5.d/ 还有 /etc/rc3.d 内的 Sxxname 与 Kxxname 有差异而已。 所以说,当执行 init 3 时,系统会: 

·  先比对 /etc/rc3.d/ 及 /etc/rc5.d 内的 K 与 S 开头的档案; 

·  在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 K 开头档案,则予以关闭; 

·  在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 S 开头档案,则予以启动;

在bash里面直接敲 “runlevel”就可以知道当前的运行等级咯。

 

核心与核心模块

启动过程中能否成功地驱动主机的硬件设备是核心(kernel)的工作。可惜一般都是压缩文件,在使用核心前就要将它解压缩后才能加载到主存储器中。

核心模块所在的目录:/lib/modules/`uname -r`/kernel

核心源码所在的目录:/usr/src/linux(安装才有的,默认是没有安装)

核心被顺利加载到系统中,会记录下以下几个信息:

核心版本:/proc/version

系统核心功能:/proc/sys/kernel

如果一个新硬件,操作系统不支持该怎么办?

重新编译核心,并加入最新的硬件驱动程序源码。

将该硬件的驱动程序编译为模块,在启动时加载该模块。

核心模块与依赖性

通常核心放在核心模块所在的目录:/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 命令可以建立该文件。

[root@www ~]# depmod [-Ane]

选项与参数:

-A  :不加任何参数时, depmod 会主动的去分析目前核心的模块,并且重新写入/lib/modules/$(uname -r)/modules.dep 当中。若加入 -A 参数时,则 depmod会去搜寻比 modules.dep 内还要新的模块,如果真找到新模块,才会更新。

-n  :不写入 modules.dep ,而是将结果输出到屏幕上(standard out);

-e  :显示出目前已加载的不可执行的模块名称

 

范例一:若我做好一个网络卡驱动程序,文件名为 a.ko,该如何更新核心相依性?

[root@www ~]# cp a.ko /lib/modules/$(uname -r)/kernel/drivers/net

[root@www ~]# depmod

以上面的范例一为例,我们的 Linux kernel 2.6.x 版本的核心模块扩展名一定是 .ko 结尾的, 当你使用 depmod 之后,该程序会跑到模块标准放置目录 /lib/modules/$(uname -r)/kernel , 并依据相关目录的定义将全部的模块捉出来分析,最终才将分析的结果写入 modules.dep 档案中的吶! 这个档案很重要喔!因为他会影响到本章稍后会介绍的 modprobe 指令的应用!

核心模块的观察:lsmod, modinfo

利用lsmod可以知道当前核心加载了多少模块。

这个命令显示的内容有:模块名称,模块的大小,此模块是否会被其他模块所使用。

利用modinfo 可以显示出模块的相关信息。

[root@www ~]# modinfo [-adln] [module_name|filename] 

选项不参数: 

-a  :仅列出作者名称; 

-d  :仅列出该 modules 的说明 (description); 

-l  :仅列出授权 (license); 

-n  :仅列出该模块的详细路径。 

范例一:由上个表格当中,请列出 mii 这个模块的相关信息: 

[root@www ~]# modinfo mii 

filename:       /lib/modules/2.6.18-92.el5/kernel/drivers/net/mii.ko 

license:        GPL 

description:    MII hardware support library 

author:         Jeff Garzik <jgarzik@pobox.com> 

srcversion:     16DCEDEE4B5629C222C352D 

depends: 

vermagic:       2.6.18-92.el5 SMP mod_unload 686 REGPARM 4KSTACKS 

gcc-4.1 

# 可以看到这个模块的来源,以及该模块的简易说明!(是硬件支持库) 

范例二:我有一个模块名称为 a.ko ,请问该模块的信息为? 

[root@www ~]# modinfo a.ko 

....(省略).... 

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

手动加入模块。

建议使用modprobe这个命令

这是因为 modprobe 会主动的去搜寻 modules.dep 的内容,先克服了模块的相依性后, 才决定需要加载的模块有哪些。insmod 则完全由使用者自行加载一个完整文件名的模块, 并不会主动的分析模块相依性!

[root@www ~]# insmod [/full/path/module_name] [parameters]

范例一:请尝试载入 cifs.ko 这个『档案系统』模块

[root@www ~]# insmod /lib/modules/$(uname -r)/kernel/fs/cifs/cifs.ko

[root@www ~]# lsmod | grep cifs

cifs                  212789  0

他立刻就将该模块加载啰~但是 insmod 后面接的模块必须要是完整的『档名』才行!那如何移除这个模块呢?

[root@www ~]# rmmod [-fw] module_name

选项与参数:

-f  :强制将该模块移除掉,不论是否正被使用;

-w  :若该模块正被使用,则 rmmod 会等待该模块被使用完毕后,才移除他! 

范例一:将刚刚加载的 cifs 模块移除!

[root@www ~]# rmmod cifs

范例二:请加载 vfat 这个『档案系统』模块

[root@www ~]# insmod /lib/modules/$(uname -r)/kernel/fs/vfat/vfat.ko

insmod: error inserting '/lib/modules/2.6.18-92.el5/kernel/fs/vfat/vfat.ko': 

-1 Unknown symbol in module

# 无法加载 vfat 这个模块啊!伤脑筋!

使用 insmod 与 rmmod 的问题就是,你必须要自行找到模块的完整文件名才行,而且如同上述范例二的结果, 万一模块有相依属性的问题时,你将无法直接加载或移除该模块呢!所以近年都建议直接使用 modprobe 来处理模块加载的问题,这个指令的用法是:

[root@www ~]# modprobe [-lcfr] module_name

选项与参数:

-c  :列出目前系统所有的模块!(更详细的代号对应表)

-l  :列出目前在 /lib/modules/`uname -r`/kernel 当中的所有模块完整文件名;

-f  :强制加载该模块;

-r  :类似 rmmod ,就是移除某个模块啰~

范例一:加载 cifs 模块

[root@www ~]# modprobe cifs

# 很方便吧!不需要知道完整的模块文件名,这是因为该完整文件名已经记录到

# /lib/modules/`uname -r`/modules.dep 当中的缘故啊!如果要移除的话:

[root@www ~]# modprobe -r cifs

使用 modprobe 真的是要比 insmod 方便很多!因为他是直接去搜寻 modules.dep 的纪录, 所以啰,当然可以克服模块的相依性问题,而且还不需要知道该模块的详细路径呢!

例题: 尝试使用 modprobe 加载 vfat 这个模块,并且观察该模块的相关模块是哪个? 

答:我们使用 modprobe 来加载,再以 lsmod 来观察与 grep 撷取关键词看看:

[root@www ~]# modprobe vfat

[root@www ~]# lsmod | grep vfat

vfat                   15809  0

fat                    51165  1 vfat <==原来就是 fat 这个模块啊!

 

[root@www ~]# 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 

则:

[root@www ~]# vi /etc/modprobe.conf

alias eth0 ne

alias eth1 ne

options eth0 io=0x300 irq=5

options eth1 io=0x320 irq=7

嘿嘿!如此一来,我的 Linux 就不会捉错网络卡的对应啰!

引导加载程序:Grub

boot loader 的两个 stage 

为了解决加载内存不足的问题,Linux 将 boot loader 的程序代码执行与设定值加载分成两个阶段 (stage) 来执行: 

·  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 中 /boot/grub/ 目录下最重要的就是配置文件 (menu.lst) 以及各种文件系统的定义!

Grub的设置文件:/boot/grub/menu.lst与安装类型

Grub优点之一就是可以动态搜索设置文件,而不需要在修改设置文件后重新安装Grub。也就是修改完/boot/grub/men.lst里的设置,下次启动就生效了。

1 与硬盘的关系

Grub对硬盘的代号设置于传统的Linux磁盘代号完全不同,它的代号类似与这样:(hd0,0)

注意:

     硬盘代号以小括号括起来。

     硬盘以hd表示,后面接一组数字。

     以“搜索顺序”作为硬盘的编号,而不是根据硬盘排线的顺序。

     第一个搜寻到的硬盘为 0 号,第二个为 1 号,以此类推; 

每个硬盘的第一个 partition 代号为 0 ,依序类推。 

整个硬盘代号为:

这样应该比较好看出来了吧?第一个硬盘的 MBR 安装处的硬盘代号就是『(hd0)』, 而第一个硬盘的第一个分割区的 boot sector 代号就是『(hd0,0)』第一个硬盘的第一个逻辑分割区的 boot sector 代号为『(hd0,4)』!

2 /boot/grub/menu.lst设置文件

接下来瞧一瞧设定档的内容了。

[root@www ~]# vim /boot/grub/menu.lst

default=0     <==预设开机选项,使用第 1 个开机选单 (title)

timeout=5     <==若 5 秒内未动键盘,使用预设选单开机

splashimage=(hd0,0)/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 控制权。 在整体设定方面的项目主要常见的有:

default=0
这个必须要与 title 作为对照,在设定档里面有几个 title ,开机的时候就会有几个选单可以选择。 由于 grub 启始号码为 0 号,因此 default=0 代表使用『第一个 title 项目』来开机的意思。 default 的意思是,如果在读秒时间结束前都没有动到键盘, grub 预设使用此 title 项目 (在此为 0 号) 来开机。

timeout=5
开机时会进行读秒,如果在 5 秒钟内没有按下任何按键,就会使用上面提到的 default 后面接的那个 title 项目来开机的意思。如果你觉得 5 秒太短,那可以将这个数值调大 (例如 30 秒) 即可。此外,如果 timeout=0 代表直接使用 default 值进行开机而不读秒,timeout=-1 则代表直接进入选单不读秒了!

splashimage=(hd0,0)/grub/splash.xpm.gz那就是这个档案提供的背景图示啦(3)!不过这个档案的实际路径写法怎么会是这样啊?很简单啊~上述的意思是:在 (hd0,0) 这个分割槽内的最顶层目录中,底下的 grub/splash.xpm.gz 那个档案的意思。想一想,如果你的 /boot 目录并没有独立成为一个分割槽, 这里会写成如何?

hiddenmenu
这个说的是,开机时是否要显示选单?目前 CentOS 预设是不要显示选单, 如果您想要显示选单,那就将这个设定值批注掉! 

整体设定的地方大概是这样,而底下那个 title 则是显示开机的设定项目。如同前一小节提到的,开机时可以选择 (1)直接指定核心档案开机或 (2)将 boot loader 控制权转移到下个 loader (此过程称为 chain-loader)。每个 title 后面接的是『该开机项目名称的显示』,亦即是在选单出现时,选单上面的名称而已。 那么这两种方式的设定有啥不同呢?

 

直接指定核心开机
既然要指定核心开机,所以当然要找到核心档案啦!此外,有可能还需要用到 initrd 的 RAM Disk 设定档。但是如前说的, 尚未开机完成,所以我们必须要以 grub 的硬盘识别方式找出完整的 kernel 与 initrd 檔名才行。 因此,我们可能需要有底下的方式来设定才行!

1. 先指定核心档案放置的 partition,再读取档案 (目录树),最后才加入档案的实际文件名与路径 (kernel 与 initrd);

 鸟哥的 /boot 为 /dev/hda1 ,因此核心档案的设定则成为:

root    (hd0,0)          <==代表核心档案放在那个 partition 当中

kernel  /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet

initrd  /initrd-2.6.18-92.el5.img

上面的 root, kernel, initrd 后面接的参数的意义说明如下:
root :代表的是『核心档案放置的那个 partition 而不是根目录』喔!不要搞错了! 以鸟哥的案例来说,我的根目录为 /dev/hda2 而 /boot 独立为 /dev/hda1 ,因为与 /boot 有关, 所以磁盘代号就会成为 (hd0,0) 啰。

kernel :至于 kernel 后面接的则是核心的档名,而在档名后面接的则是核心的参数。 由于开机过程中需要挂载根目录,因此 kernel 后面接的那个 root=LABEL=/1 指的是『Linux 的根目录在哪个 partition 』的意思。 还记得
第八章谈过的 LABEL 挂载功能吧? 是的,这里使用 LABEL 来挂载根目录。至于 rhgb 为色彩显示而 quiet 则是安静模式 (屏幕不会输出核心侦测的信息)。 
initrd :就是前面提到的 initrd 制作出 RAM Disk 的档案档名啦!

2. 直接指定 partition 与档名,不需要额外指定核心档案所在装置代号

kernel  (hd0,0)/vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet

initrd  (hd0,0)/initrd-2.6.18-92.el5.img

老实说,鸟哥比较喜欢这种样式的文件名写法,因为这样我们就能够知道核心档案是在哪个装置内的某个文件名, 而不会去想到我们的根目录 (/, root) 啦!让我们来想想 /boot 有独立分割与无独立分割的情况吧!

例题: 我的系统分割是: /dev/hda1 (/), /dev/hda2 (swap) 而已,且我的核心档案为 /boot/vmlinuz,请问 grub 的 menu.lst 内该如何撰写核心档案位置? 

答:我们使用迭代的方式来了解一下好了。由于核心文件名为 /boot/vmlinuz,转成装置文件名与代号会成为如下的过程:

源文件:  /boot/vmlinuz ↓

Linux 装置:(/dev/hda1)/boot/vmlinuz ↓

grub  装置:(hd0,0)/boot/vmlinuz

所以最终的 kernel 写法会变成: 

kernel (hd0,0)/boot/vmlinuz root=/dev/hda1 ...

例题:同上,只是我的分割情况变成: /dev/sda1 (/boot), /dev/sda5 (/) 时? 

答:由于 /boot 被独立出来了,所以情况会不一样喔!如下所示:

源文件:  /boot/vmlinuz ↓

Linux 装置:(/dev/sda1)/vmlinuz ↓

grub  装置:(hd0,0)/vmlinuz

所以最终的 kernel 写法会变成: 

kernel (hd0,0)/vmlinuz root=/dev/sda5 ...

利用 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 只要这样就够了:

[root@www ~]# vi /boot/grub/menu.lst

....前略....

title Windows partition

         root (hd0,0)    <==设定使用此分割槽

         chainloader +1  <== +1 可以想成第一个扇区,亦即是 boot sector

上面的范例中,我们可以很简单的这样想:那个 (hd0,0) 就是 Windows 的 C 槽所在磁盘, 而 chainloader +1 就是让系统加载该分割槽当中的第一个扇区 (就是 boot sector) 内的开机管理程序。 不过,由于 Windows 的开机碟需要设定为活化 (active) 状态,且我们的 grub 预设会去检验该分割槽的档案系统。 因此我们可以重新将上面的范例改写成这样:

[root@www ~]# vi /boot/grub/menu.lst

....前略....

title Windows partition

         rootnoverify (hd0,0)   <==不检验此分割槽

         chainloader +1

         makeactive             <==设定此分割槽为开机碟(active)

grub 的功能还不止此,他还能够隐藏某些分割槽。举例来说,我的 /dev/hda5 是安装 Linux 的分割槽, 我不想让 Windows 能够认识这个分割槽时,你可以这样做:

[root@www ~]# vi /boot/grub/menu.lst

....前略....

title Windows partition

         hide (hd0,4)           <==隐藏 (hd0,4) 这个分割槽

         rootnoverify (hd0,0)

         chainloader +1

         makeactive

原创粉丝点击