⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common-start-flow.html

📁 学习linux的工具书
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
   <meta name="Author" content="Edward Fu">
   <meta name="GENERATOR" content="Mozilla/4.05 [zh-CN] (X11; I; Linux 2.1.127 i686) [Netscape]">
   <title>Freesoft Linux FAQ -- 开机启动流程介绍</title>
</head>
<body>
&nbsp;
<br>Linux 开机程序之研讨
<br>CCCA 资工86 许景华
<br>&nbsp;
<p>各位是否曾经对电脑整个开机的流程感到好奇呢 ? 这一次 , 我们所要讨论的
<br>主题 , 就是 Linux 从开机的一瞬间到 login 为止 , 到底发生了什么事情
?
<p>想必各位都知道 , 在刚开机时 , 由于 80x86 的特性 , CS ( Code Segment
)
<br>这个寄存器中全部都放着 1 , 而 IP ( Instruction Pointer ) 这个寄存器
<br>中全部都放着 0 , 换句话说 , CS=FFFF 而 IP=0000 , 此时 , CPU 就依据
<br>CS 及 IP 的值 , 到 FFFF0H 去执行那个地方所放的指令 . 这时候 , 由于
<br>FFFF0H 已经到了高位址的顶端 , 所以 , FFFF0H 这个地方 , 总是会放一个
<br>JMP 指令 , 跳到比较低的位址 . 接著 , ROM BIOS 就会作一些检查的动作
<br>像内存 , 键盘 等...... 并在我们俗称的 UMB ( Upper Memory Block )
<br>之中扫描 , 看看是否有合法的 ROM 存在 ( 比如 SCSI 卡上的 ROM ) .
<br>假如有 , 就到里面去执行一些东西 , 执行完之后再继续刚才的行程 . 到了
<br>最后 , 读取硬盘上的第一个 sector . 在这里 , 我假设各位由硬盘启动
<br>因此 , 就硬盘的构造而言 , 它的第一个 sector 称为 MBR ( Master Boot
<br>Record ) . 因为一个 sector 是 512 bytes , 而 MBR 这 512 bytes 可分
<br>为两个部份 , 第一个部份为 Pre-Boot 区 , 占了 446 bytes ; 第二部份
<br>是 Partition Table , 占了 66 bytes . Pre-Boot 区的作用之一 , 就是
<br>去看看那个 Partition 被标成 Active , 然後去读那个 Partition 的 Boot
<br>区 .
<p>在 Linux 的启动方面 , 一般人最常把 LILO 放在 MBR 或 Superblock
<br>假如你把 LILO 放在 MBR , 那很明显的 , 当读取到 MBR 的时候 , LILO
<br>就被执行 , 此时 , 你的屏幕上会出现 boot: 接着 , 就进行 Load Kernel
<br>的动作 . 在另一方面来说 , 假如你把 LILO 安装在 Superblock , 通常你
<br>还会有一个管理开机的程序 , 也许是放在 MBR ( 像 OSBS ) 或者是放在一
<br>个单独的 Partition ( 像 OS/2 的 Boot Manager ) . 再由这个管理开机
<br>的程式去读取 LILO , 进而做 Load Kernel 的动作 .
<p>好了 , 到了目前为止 , 我们已经讲到 Load Kernel 的动作 . Kernel 被
<br>load 到 memory 中之后 , 接着进行一连串 probe 周边的动作 , 像串口
<br>并口 , 软盘 , 声卡 , 硬盘 , 光驱 等 ...... 接着 mount root
<br>partition . 在这之后 , kernel 会起动 init 这个 process . init 这
<br>个 process 的 PID 为 1 , 它是所有 process 的祖先 .
<p>接下来呢 ? 系统就开始执行 /rc.d/rc.S , 在这里 , 我们暂时打住 ,
<br>先对大概的 initialization script 执行的顺序作一个浏览 , 请看下面
<br>的流程 :
<p>init[1]
<br>rc.S begin &lt;--- 目前我们已经讲到这里
<br>rc.serial begin
<br>rc.serial end
<br>rc.S end
<br>init[1] enter runlevel 5
<br>rc.M begin
<br>rc.inet1 begin
<br>rc.inet1 end
<br>rc.inet2 begin
<br>rc.inet2 end
<br>rc.font begin
<br>rc.font end
<br>rc.local begin
<br>rc.local end
<br>rc.M end
<br>login
<p>上面的流程清楚的指出 , 在 rc.S 这个 shell script 中 , 会去执行 rc.serial
<br>接着再执行 rc.M , rc.M 中又包含了 rc.inet1 , rc.inet2 , rc.font , rc.local
<br>最后执行 login . 在下面的内容中 , 将为各位介绍这几个 shell script
<br>从下面开始 , 凡是每一列之前有一个 # 的 , 为原来 shell script 中的注释
<br>有两个 # 的 , 为笔者加上的注释 , 当然啦 , 没有任何 # 的为 shell script
<br>的内容 , 而对命令或内容的解释 , 一律都写在命令或内容的前面 .
<br>首先由 rc.S 开始 :
<p>***************************** rc.S **********************************
<p>#!/bin/sh
<br>#
<br># /etc/rc
<br>#
<br># These commands are executed at boot time by init(8).
<br># User customization should go in /etc/rc.local.
<p>echo '======== rc.S is running ! System Initializing Now !!! ========'
<br>PATH=/sbin:/usr/sbin:/bin:/usr/bin
<p>## 打开所有 swap ! 下面 /sbin/swapon -a 的意思是 : 使得 /etc/fstab 中被记录
<br>## 成 swap 的 device 全部启动 .
<p>/sbin/swapon -a
<br>&nbsp;
<p>## 喔 ! 下面这个指令 update 就很重要了 , 它负责每隔一段固定的时间 ,
就将
<br>## buffer 中的资料 , 利用 sync 写回磁盘上 , 并将 superblock 做 update
<br>## 的动作 . 使用 ps 这个指令看看有那些 process , 就可看到 update 还有一个
<br>## bdflush , 这两个 process 都是必然要存在的 , 可不要随便砍掉 , 要不然
,
<br>## 万一系统 crash 了 , 那磁盘里面的资料就不是最新的了 ......
<p>/sbin/update &amp;
<br>&nbsp;
<p>## 利用 echo -n >> 制造一个文件 , 并用 rm -f 这个档案来测试 root partition
<br>## 是不是 read-only 或者是可读写
<p>READWRITE=no
<br>if echo -n >> "Testing filesystem status"; then
<br>rm -f "Testing filesystem status"
<br>READWRITE=yes
<br>fi
<br>&nbsp;
<p>## 假如 root partition 是 read-only 就作 fsck 的动作 , 假如不是 read-only
<br>## 而是 read-write 的话 , 就做下面 else 之后的动作
<p>if [ ! $READWRITE = yes ]; then
<br>## 利用 fsck 做检查及修复文件系统的工作 , 后面接的两个参数 -A , -a
.
<br>## -A 的意思是 : fsck 会依据 /etc/fstab 中的记录 , 去检查所有的文件
<br>## 系统 ; 而 -a 就是 auto 的意思 , 当 fsck 有修复的动作时 , 它不会问
<br>## 你问题 , 而直接修复 .
<p>/sbin/fsck -A -a
<br>&nbsp;
<p>## 假如 fsck 有 error , [ $? -gt 1 ] 括号里面的意思是 : 若上个命令的
<br>## 传回值大于 1 , 而上个命令就是 fsck . 让我们看看 fsck 的传回值 :
<br>## 0 - No errors
<br>## 1 - File system errors corrected
<br>## 2 - File system errors corrected, system should
<br>## be rebooted if file system was mounted
<br>## 4 - File system errors left uncorrected
<br>## 8 - Operational error
<br>## 16 - Usage or syntax error
<br>## 128 - Shared library error
<br>## 很明显的 , 若有任何错误产生的话 , 那 fsck 的传回值都大于 1 . 其实
<br>## 就我的观点认为 , 应该写成 if [ $? -ge 1 ] 比较好 . 既然有错呢 ,
系统
<br>## 应该就要跳至单用户模式 , 在单用户模式中主要就是 /etc/rc.d/rc.K
<br>## 中的两件事 : 关掉 swap 及 卸下所有的文件系统 , 而最后重新 login
.
<br>## 一般正常的情况下 , if 下面这一大段是不会执行的 , 而会跳至下面
<br>## 标有 ************************* Normal 1 *************************
<p>if [ $? -gt 1 ] ; then
<br>echo
<br>echo
<br>echo "**************************************"
<br>echo "fsck returned error code - REBOOT NOW!"
<br>echo "**************************************"
<br>echo
<br>echo
<br>/bin/login
<br>fi
<p>## ****************************** Normal 1 **************************
<br>## 当 fsck 检查没有错误之后 , 就把 root partition 重新 mount 上来
<br>## 下面指令的参数有三个 , -w 代表mount 成可读写 , -n 代表把一个 file-
<br>## system mount 上来 , 但不会把记录写到 /etc/mtab 中 , 在上次对 /etc/mtab
<br>## 介绍时有提到 , 当我们使用 mount 这个指令把一个 filesystem mount
上来
<br>## 的时候 , /etc/mtab 就会记录 ! 利用 -n 这个 option 可使得做 mount
的动
<br>## 作 , 却不会记录 . -o 后面可以接许多的选项 , 在这里 , 我们给它的选项是
<br>## remount . remount 的意思是 : 重新 mount 一个已经被 mount 的 filesystem
<br>## 这个选项通常被用来改变该 filesystem 的读写标志 ,尤其是把 filesystem
<br>## 从 read-only 的状态 , 改变成 read-write 的状态 .
<p>echo "Remounting root device with read-write enabled."
<br>/sbin/mount -w -n -o remount /
<br>&nbsp;
<p>## 在前面的情况中 , 都是 root partition 为 read-only 的状态下 , 所做的一些
<br>## 工作 , 到了最后一个指令 /sbin/mount -w -n -o remount / , 才把 root
<br>## partition mount 成 read-write . 各位有没有看到前面那行 :
<br>## if [ ! $READWRITE = yes ]; then ..... 下面这个 else 就是与这个 if
对应
<br>## 也就是说 , 前面那个 if 的区块中 , 所作的工作都是在 root partition
<br>## read-only 的条件成立下所作的事 , 那很明显的 , 下面这个 else 就是
root
<br>## partition 为 read-write 的条件下所作的工作 . 假如你的 root partition
<br>## 为 read-writeable 的话 , 那么系统就会显示下面的信息 . cat &lt;&lt;
EOF 所作的
<br>## 事 , 就是把 EOF 之前的信息全部显示在屏幕上 :
<br>## 我想 , 下面的信息写得很明显了 , 它说 : 你的 root partition 被 mount
<br>## read-write , 没有办法检查 , 要使检查的动作能够顺利的进行 , 你必须把
<br>## root partition mount 成 read-only ! 那要怎么做呢 ? 很容易 , 只要利用
<br>## rdev -R / 1 就可以了 ......
<p>else
<br>cat &lt;&lt; EOF
<p>*** Root partition has already been mounted read-write. Cannot check!
<br>For filesystem checking to work properly, your system must initially
mount
<br>the root partition as read only. Please modify your kernel with 'rdev'
so
<br>that
<br>it does this. If you're booting with LILO, type:
<br>rdev -R /vmlinuz 1
<br>(^^^^^^^^ ... or whatever your kernel name is.)
<p>If you boot from a kernel on a floppy disk, put it in the drive and
type:
<br>rdev -R /dev/fd0 1
<p>This will fix the problem *AND* eliminate this annoying message. :^)
<p>EOF
<br>&nbsp;
<p>## 下面这个指令没什么好说的 , 就是暂停 10 秒钟 , 让 user 能够有充足的
<br>## 时间看完上面的信息
<p>sleep 10
<br>fi
<br>&nbsp;
<p>## 删除 /etc/mtab /etc/nologin /etc/utmp
<p>/bin/rm -f /etc/mtab* /etc/nologin /etc/utmp
<br>&nbsp;
<p>## 制造 /etc/utmp , 这是一个很典型制造空文件的写法 . /dev/null 这个
node
<br>## 蛮有趣的 , 在某一方面来说 , 它有点像是一个 " 黑洞 " . 怎么说呢 ?
<br>## 各位可以试试看下面的指令 ls >> /dev/null , 当你使用这个指令之后会
<br>## 发生什么事呢 ? 什么也没发生 , 而且 ls 的输出就好像被丢到黑洞里 ,
<br>## 影无踪了 . 那也许你会想 : 那这有什么用 ? 我的回答是 : 的确没有什么
<br>## 很大的用处 , 但当你想抑制输出的信息时 , 你就会用得到了 .
<p>cat /dev/null >> /etc/utmp
<br>&nbsp;
<p>## 依据 fstab ( filesystem table ) 中的描述 , 自动的挂上文件系统
<br>## 但此时因为 TCP/IP 还没有设定 , 故不用 NFS
<p>echo 'Mount Filesystem !!!'
<br>/sbin/mount -avt nonfs
<br>&nbsp;
<p>## 设定系统的时钟 . 下面这几行所做的事就是 : 看看 /sbin/clock 这个文件是
<br>## 不是可执行的 , 假如可以执行 , 就把 CMOS 中的时间设定为系统的时间
.
<p>if [ -x /sbin/clock ]; then
<br>echo 'Set System Clock'
<br>/sbin/clock -s
<br>fi
<br>&nbsp;
<p>## 下面的四行若没有 mark , 则每次开机 issue 及 motd 都会被改变 , 这应该
<br>## 可算是 FAQ 级的问题了 ...... 因为我有自己设计的 issue 及 motd ,
所以
<br>## 下面的四行前面都有 # , 被注释掉 .
<br>## 假如你要有自己的设定 , 下面一定都要 mark 起来
<p>#echo > /etc/issue
<br>#echo Welcome to Linux /bin/uname -a | /bin/cut -d\ -f3. >> /etc/issue
<br>#echo >> /etc/issue
<br>#echo "/bin/uname -a | /bin/cut -d\ -f1,3. (Posix)." > /etc/motd
<br>&nbsp;
<p>## 接下来 , 将执行 rc.serial , 顾名思义 , rc.serial 是作串口设定的工作
<br>## 在 rc.serial 中 , 内容虽然也是很简单 , 但并不像 rc.S 那样直接 .
换句话
<br>## 说 , 读者至少要 " 稍微 " 懂一点 shell programming , 所以说呢 , 假如
<br>## 还不会 shell programming 的读者呢 , 都应该赶快去找一本书来看一下

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -