A!die Software Studio Welcome to A!Die Software Studio

第一章 准备出发

by adie
May, 2012
   上一章   回目录   下一章   

第一篇 构建 LFS 6.3 系统

第一章 准备出发

在开始构建系统之前,还有一些准备工作要做,这些内容包括:下载 LFS,下载 LiveCD,创建虚拟主机,对硬盘进行分区,检查宿主系统等等。这些准备工作同样非常重要,这里准备的内容会对之后的操作造成持续的影响。本章将对这些内容一一进行介绍,如果你有过虚拟主机的使用经验,你可以选择性的跳过本章的部分内容。

1.1 下载 LFS 和 LiveCD

在浏览器中打开 LFS 的主页 http://www.linuxfromscratch.org 可以看到,LFS 包括了以下几部分:

1. LFS: 基本的系统构建指南,是其他项目的基础。
2. BLFS:扩展已经安装好的 LFS 系统,让它更个性化,更好用。
3. ALFS:提供了自动管理和构建 LFS 系统的工具。
4. CLFS:在各种系统上交叉编译出 LFS 系统来。
5. HLFS:注重于构建高安全度的 LFS 系统。
6. Hints:收集了一些 LFS 和 BLFS 中没有的文档,它们用于修改你的系统。
7. LiveCD:提供了一个构建 LFS 的宿主主机系统,并且可以作为应急盘使用。
8. Patches:上面这些文档中用到的补丁。

现在,你需要浏览 LFS 项目中的 Download 子目录,从中找到 LFS 6.3 的 PDF 文档,并把它下载下来,如果浏览英文网站不是很顺畅,可以直接使用 http://archive.linuxfromscratch.org/lfs-museum/6.3/LFS-BOOK-6.3.pdf.bz2 这个链接来下载。虽然文档中的内容在本文中都有提及,但是阅读原始的这份文档还是有用的。

然后我们再查看 LiveCD 项目中的 Download 目录,随意选择一个镜像,可以看到如下的一些文件:

注意不同的镜像提供的文件有可能不同,你需要找到包含了 lfslivecd-x86-6.3-r2160.iso 这个文件的镜像。

这些文件名中的 x86 标明了它是 32 位版本,x86_64 是 64 位版本,尽管你的 CPU 可能是 64 位的,LFS 仍然建议你使用 32 位的版本。构建 64 位的系统并不比 32 位系统快多少,可执行文件会占用更大的磁盘空间,唯一的好处是可以使用高于 4GB 的内存,对于我们的虚拟机来说,我们用不到那么大的内存。而且构建出的 64 位系统是纯的 64 位系统,只能运行 64 位的可执行文件,要运行 32 位的程序,你还需要构建一套 32 位的库,你需要使用多库系统。这些并不在本文的范围内,也不在 LFS 的范围内。

其中的 6.3 表明包含了官方的 LFS 6.3 指南内容(64 位版本包含的是非官方的 LFS 指南)。rxxxx 是 livecd 的构建版本号,应该选择使用最新的稳定版本,目前最新的是 r2160。

带 -nosrc 后缀的表明光盘中不包含构建 LFS 的源代码,你需要自行下载源代码。带 -min 后缀的表明它不包含源代码,也不包含 X Window 系统(图形化桌面)。为了省掉自行下载源代码的麻烦,我们选择下载 lfslivecd-x86-6.3-r2160.iso 这个版本(其实我是想下载含源代码,不包含 X Window 系统的版本的,可惜没有 ...)。其中一个下载链接为 ftp://anduin.linuxfromscratch.org/LFS-LiveCD/lfslivecd-x86-6.3-r2160.iso

如果你英文不错的话,在下载的这段时间你可以看看以下一些内容:

1. http://www.tldp.org/HOWTO/Software-Building-HOWTO.html (如何在 linux 下编译软件)
2. http://www.linuxfromscratch.org/hints/downloads/files/essential_prereading.txt (构建 LFS 系统所需的知识点)

1.2 创建虚拟主机

首先,请确保已经下载并安装好了 VMware Workstation 7.1.4。不同的版本或不同的虚拟机软件也是可行的,只是和下面的步骤不一定完全吻合,但不影响 LFS 系统的构建。

1. 点击 Home 页面中的 New Virtual Machine 图标。如果没打开 Home 页面,也可以使用菜单 File -> New -> Virtual Machine。

2. 在弹出的对话框中选择 Custom 并点击 Next。

3. 保持默认选择的 Workstation 6.5-7.x 选项点击 Next。

4. 选择 Installer disc image file(iso) 选项,点击 Browse... 按钮,选择你刚刚下载的 LiveCD 文件。确定后会看到一个黄色的警告标识,告诉你不能检测到光盘中的操作系统,需要你手动指定。没有关系,点击 Next 来手动指定就好。

5. 在 Guest operating system 中选择 Linux 项,Version 中选择 Other Linux 2.6.x kernel 项,然后 Next 。

6. 在 Virtual machine name 中输入一个你喜欢的系统名字,比如 aslinux,然后点击 Browse... 按钮,选择你的虚拟机存放的位置,然后 Next。

7. 选择 CPU,如果你有多个 CPU,建议也只是用 1 个,每个 CPU 也只是用 1 核。如果是一个单核的 CPU,就没得选了,直接 Next。

8. 设置内存,建议 1G 大小,Next。

9. 网络设置,选择 Use network address translation (NAT),Next。

10. 设置IO 类型,使用默认的 LSI Logic (Recommended) 就好,Next。

11. 设置硬盘,选择 Create a new virtual disk,然后 Next。

12. 硬盘类型,使用默认的 SCSI (recommended),然后 Next。

13. 设置硬盘大小,建议设置最大硬盘 Maximum disk size 为 80G,然后确保 Allocate all disk space now 为未选中状态,这样生成的文件并不会实际占用你 80G 硬盘空间的,只会占用你使用的数据大小。如果你的单个分区上没有 80G 剩余空间,或者你的文件系统不支持大文件(比如 FAT),请选择 Split virtual disk into multiple files(分隔硬盘为多个文件) 项,否则为了性能和管理方便,请选择 Store virtual disk as a single file(存储硬盘为单个文件)。完成后单击 Next。

14. 选择保存硬盘的文件,建议使用 aslinux_sda 这样的名字,便于以后添加硬盘时好区分。

15. 选中 Power on this virtual machine after creation(创建完成后启动虚拟机),点击 Finish 按钮来启动虚拟机。虚拟机启动后将会看到如下的画面:

到此,虚拟机的创建就完成了,我们以后的操作都将在刚刚创建的虚拟机上进行

1.3 基本命令介绍

为了方便之后的操作,在这里对使用频繁的 Linux 命令做一个简要的说明。详细的命令可以参考 http://www.adintr.com/down/books/linux_command.chm,熟悉 unix 系统的可以直接跳过。

cd# 返回用户的主目录
cd <目录名># 改变当前目录
pwd # 显示当前目录
mkdir <目录名> # 创建目录
ls # 显示当前目录下的文件和子目录
ln # 建立符号连接
cat <文件名> # 显示文件内容
man <命令> # 浏览命令的指导手册
tar xvf <文件名> # 解压缩文件到当前目录
wget <URL> # 下载制定的 URL 到当前目录
source <文件名> # 执行文件中的命令
make # 执行当前目录下 Makefile 中的脚本,通常是编译代码
grep <正则表达式> <文件>        #找到文件中匹配正则表达式的行
cat > <文件名> << "EOF" # 用输入的内容创建文件,EOF 结束输入

要点指示 1:LINUX 和 WINDOWS 文件系统的区别

硬盘是计算机存储永久数据的主要设备,硬盘只提供了基本的按扇区来读写数据的功能。操作系统需要在更高层面来为用户存储数据提供支持。在这方面,几乎所有的操作系统都使用文件来组织硬盘上的数据。如果你熟悉计算机,相信你对文件和目录(或文件夹)不会陌生。文件系统包括两个层面,第一是文件和目录结构以什么方式存储在磁盘上,第二是给用户提供了什么样的抽象层次。

关于第一个问题,每一个操作系统都有自己的实现方案:windows 使用 FAT,FAT32,NTFS 等格式;Linux 使用 ext2,ext3,ext4 等格式;Mac X 使用 HFS 等格式。

关于第二个问题就统一得多了,几乎所有的操作系统都提供树形的目录结构,区别主要在文件名的长度,路径的长度这些具体细节上了: 在 Windows 中,每一个磁盘分区都有一个根目录,目录之间使用 “\” 进行分隔,文件和目录名不区分大小写;在 Linux 中,系统只有一个根目录,磁盘分区只能挂载到这一棵目录树的某一个节点上,目录之间使用 “/” 进行分隔,文件和目录名通常是要区分大小写的。

另外,Windows 上的一个文件通常就是一段存储在硬盘上的数据,即真实的文件。而 Linux 系统中的文件除了存储在硬盘上的数据文件外,还有许多其它设备或对象也被抽象成文件,比如屏幕终端、键盘、内存、硬盘(很奇怪哈,文件本身是存储在硬盘上的,而现在硬盘又成了一个文件了)、内核对象等等。Linux 的文件系统所描述的内容比 Windows 要丰富得多。

经过众多版本的演化,UNIX 的目录结构现在已经被标准化了,Linux 在组织目录结构的时候也应该遵循这个标准。 FHS 的标准文档: http://www.pathname.com/fhs/pub/fhs-2.3.html 中文翻译版: http://www.adintr.com/media/books/fhs.pdf

1.4 LiveCD系统

紧接上一节的操作,由于我们创建虚拟机的时候已经设置好了光盘镜像,所以系统启动后会自动从光盘引导,现在进入的系统就是 LiveCD 提供的一个宿主 Linux 系统。这是一个完整的操作系统,不需要安装到硬盘上,直接通过光盘来使用,非常方便,当系统出现故障时也可以通过载入这个系统来进行修复。

把鼠标移到虚拟机的画面里,点击一下,你会看到鼠标指针消失了,这表明现在你现在的键盘和鼠标操作都是对虚拟机里面的系统进行的。要让你的鼠标和键盘退出虚拟机系统,请同时按住 Ctrl + Alt 键。一些常用 VMware 快捷键有:

Ctrl + G 进入虚拟机,和在虚拟机屏幕里点击鼠标是一样的
Ctrl + Alt 退出虚拟机
Ctrl + R 重启
Ctrl + E 关机
Ctrl + Alt + Enter 切换全屏和窗口模式

好了,现在进入虚拟机,点击回车,屏幕滚动一些字符后出现如下的选择时区画面,使用键盘的上下箭头选中 Asia/Chongqing (亚洲/重庆)后回车。

之后是选择时钟,使用默认的 Localtime 本地时钟即可,回车之后是选择语言,使用上下箭头选中 English, USA (UTF-8) 然后回车。

之后是一个设置的确认画面,这里还有一些更多的字体设置等等,使用默认值回车即可。然后进入到如下画面:

这里除了一些版本信息,还给了我们一些提示:

1. 构建 LFS 系统的源代码在 /lfs-sources 这个目录下;
2. 光盘里包含了一份 HTML 版的 LFS 手册,其位置在 /usr/share/LFS-BOOK-6.3-HTML 目录下,当然我们其实已经下载了一份 PDF 格式的了,毕竟在虚拟机上浏览这一份不是很方便;
3. 使用 greeting 命令可以再次显示这些信息。

最后一次敲击回车,就出现了我们要进行工作的命令行了,首先来试试输入 clear 命令清空一下屏幕上过多的信息:

由于我们现在是从光盘直接启动的,所以你做的任何操作在重启后都会消失,在开始正式构建系统之前,你可以随意使用各种命令来熟悉一下系统,即使系统遭到破坏也没有关系,只需要重启一下就好了。

如果你以前从未使用过命令行,或许会觉得无所适从,没有关系,慢慢熟悉后就会发现,命令行很多时候都比图形化界面更加方便灵活。图形化界面的操作方式和命令行有些不同:大多数的图形化程序都需要用户和应用程序持续的进行交互,你需要不停的告诉应用程序如何来完成最终的目标;命令行程序不同,你需要在一开始就提供如何完成目标的所有信息,然后通过命令告诉应用程序,之后程序的运行就不需要你进行操作了,只需要等待结果就行了。如果你之前使用过 DOS 或 Windows 下面的命令行程序,需要注意一下,和Windows使用 / 来传递参数不同,UNIX 程序的参数都是通过 - 或 -- 来传递的;另外 UNIX 的目录分隔符号是 /,而不是 windows 的 \ 。

虽然我们的所有工作几乎都是通过命令行来完成的,但是在 LiveCD 里还是包含了一个 X Window 系统,你在体验过枯燥了命令后或许想看看这个图形界面。要进入 X Window 系统,在命令行下输入:

root [ ~ ]# startx

注意,我们以后的命令都将使用这种格式:前面的 root [~]# 是命令提示符,不是输入的内容,这个提示符是变化的,它给我们提供了一些重要的信息,比如当前用户,当前目录等等。这个命令提示符能够展示一部分命令执行的环境,所以我觉得提供出来是很有意义的,在 LFS 指南中,命令是没有包含命令提示符的,所以很多地方不是很明确命令是在哪里执行的。斜体部分的 startx 是输入的命令,以后的输入都会用斜体来表示,而命令的输出会用另一种字体的非斜体来表示,所有的命令输入完成后都要使用回车才能执行。在复制命令来进行操作时要特别注意,不要复制到了命令提示符或输出的内容。

执行 startx 命令后,界面会出现一个警告框:

意思是说无法检测到显示器类型,所以使用了 800 X 600 分辨率,60 Hz 的刷新率来进行显示,这个无所谓,点击 Okay 进行 X Window 系统,进入后的桌面如下:

你可以随意操作一下这个桌面系统,玩够了使用 Ctrl + Alt + Backspace 键来退出图形界面。回到命令行:

Linux 是一个多终端的操作系统,你可以同时登陆几个命令行,在 LiveCD 里你可以使用 Alt + F1, Alt + F2, Alt + F3,Alt + F4,Alt + F5,Alt + F6 来进行切换。当其中一个终端在执行某些耗时的操作时,你可以切换到其它终端继续使用命令行,而不必等待。当然,你不能在另一个终端里面使用依赖于前一终端中命令结果的操作。在构建 LFS 系统的过程中,确保你始终在使用同一个终端来工作。

1.5 使用 ssh 连接 LiveCD 系统

由于 LiveCD 系统是存储在光盘上的,每次重启后系统都会还原,而安装 VMware-tools 工具又要求重启系统后才能生效,所以我们没有办法在 LiveCD 上安装 VMware-tools。没有 VMware-tools,我们就无法在现有系统(Windows)和虚拟机(LiveCD)之间进行拷贝粘贴,对于一些复杂命令来说,不使用拷贝直接输入非常的麻烦,也很容易出错。

为了解决这个问题,我们采用 ssh 的方式来管理虚拟机里的系统。SSH 是 Secure Shell 的缩写,它使用加密的协议来提供远程登录会话,保证了安全性,是 UNIX 管理远程服务器的主要手段。要使用 SSH,我们需要一个在 LiveCD 中启动一个服务器程序,然后在 Windows 下面是用一个客户端来连接。

启动虚拟机,然后用如下的命令来启动 ssh服务:

root [ ~ ]# /etc/rc.d/init.d/sshd  start

其中的 /etc/rc.d/init.d/sshd 是一段脚本,可以向它传递 start/stop/restart/status 等参数。这个脚本会根据参数来启动或停止 /usr/sbin/sshd 守护进程,sshd 进程负责提供 ssh 服务。第一次运行这个命令会首先生成用于加密的证书,然后再启动服务,结果如下:

服务停止后再次启动则不需要这个过程了:

要点指示 2:LINUX 的守护进程

守护进程(daemons)相当于 Windows 下的服务,是一种长期生存的在后台运行的进程。它们独立于控制终端,周期性的执行某些任务或处理某些事件。许多的守护进程都是在系统启动时启动,系统关闭时停止的。守护进程的文件名大都使用 d 作为结束来表明它是一个守护进程。常见的守护进程包括:crond,httpd,xinetd,sshd 等等。

sshd服务启动后,我们还需要修改 root 的密码才能登陆,使用 passwd命令,并两次输入相同的密码后即设置成功。注意输入的密码不会回显,也不会显示成 * 号。

最后,我们要看看这台主机的 IP 地址,输入以下命令:

root [ ~ ]# ifconfig eth0 | grep 'inet addr'
           inet addr:192.168.237.131 Bcast:192.168.237.255 Mask:255.255.255.0

这里使用了两个命令,第一个 ifconfig 是配置网络的常用命令,参数eth0 代表第一张网卡,使用 ifconfig eth0 后将会得到网卡的一些参数信息;然后我们通过管道把第一个命令的结果传递给了第二个命令 grep,它使用 'inet addr' 去匹配上一个命令的结果,输入包含了 'inet addr' 的行,这样我们就得到了虚拟网卡的 IP 地址了。

输出的 inet addr 后面的 192.168.237.131(在你的系统上可能不同),就是你的虚拟机的 IP 地址,记下这个 IP 地址稍后要用。

要点指示 3:管道

管道是 Linux 里常用的一种进程间通信方式,从本质上说,管道也是一种文件,它是系统提供的一块固定大小的缓冲区(通常为一个页面大小,4k),它实现了一个先进先出(FIFO)的队列结构,从管道的一端写入数据,可以从管道的另一端读取到。管道分为命名管道和匿名管道,命名管道可以通过名字进行引用;匿名管道只能通过句柄引用,适用于具有一定关系的进程之间。

我们在使用 shell 运行程序时,shell 会自动为进程打开三个文件句柄:stdin,标准输入,默认是键盘;stdout,标准输出,默认是屏幕终端;stderr,标准错误输出,默认也输出到屏幕。在两个命令之间使用 ‘|’符号后,shell 将创建一个管道,对于‘|’之前的命令进程,shell不再打开默认的屏幕终端,而是使用这个管道来代替进程的标准输出。 对于‘|’之后的命令进程,shell 不再打开默认的键盘作为标准输入,而是使用这个管道来作为标准输入。这样就把‘|’之前的命令输出作为‘|’之后的命令输入了。

管道是组成复杂 Linux命令的主要方式之一,它极大的提高了使用Linux命令的灵活性和执行效率。管道也可以级联使用,第一个输出作为第二个的输入,第二个的输出作为第三个的输入,第三个的输出作为第四个的输入......

好了,虚拟机系统到这里就配置完成了,接下来就可以在 Windows 下使用 SSH 客户端来进行连接了。SSH 的客户端软件很多,这里使用 putty 为例来简要说明。

启动 putty 后在左侧选中 Session 项,然后在右边的 Host Name (or IP address) 下面填入刚刚得到的虚拟机的 IP地址 192.168.237.131,然后点 Open 按钮,第一次连接会弹出一个证书的警告窗口,不用理会,点击 [是] 即可。

之后将会看到窗口中打印出了 login as: 的提示,输入 root 后回车,然后输入之前在虚拟机中设置的 root 密码,命令提示符就出来了:

在这里输入命令和在虚拟机的终端输入命令效果基本是一样的,不过在会话丢失后某些环境变量可能会消失,出现这种情况时你需要重新设置一下环境变量再继续。

在 putty 的终端里面,按住鼠标左键拖动即可将选中的内容复制下来,点击鼠标右键可以进行粘贴。

从现在开始,你关闭虚拟机的时候需要使用 Suspend,以便稍后进行恢复,如果使用了 Power Off 或 Reset 之类的操作,你就需要把之前在虚拟机里进行的操作全部重复一遍才行。另外,你还可以使用 Take Snapshot... 来进拍摄快照,以后就可以随时恢复到你拍摄快照的时候。以上操作都可以在窗口 Tab 页的右键菜单里找到:

1.6 检查宿主系统

安装 LFS 系统对宿主的一些工具和版本都有一定的要求,我们是直接使用的 LFS LiveCD 作为宿主系统,可以保证满足了这些要求,不过也可以走一下这个检测的流程,对于使用其它系统作为宿主系统的来说这一步是必须的。

LFS 6.3 要求的最小软件包及其版本如下:

1. Bash-2.05a
2. Binutils-2.12 (更高的版本未测试,不推荐)
3. Bison-1.875
4. Bzip2-1.0.2
5. Coreutils-5.0 (或者 Sh-Utils-2.0, Textutils-2.0, Fileutils-4.1)
6. Diffutils-2.8
7. Findutils-4.1.20
8. Gawk-3.0
9. Gcc-3.0.1 (更高的版本未测试,不推荐)
10. Glibc-2.2.5 (更高的版本未测试,不推荐)
11. Grep-2.5
12. Gzip-1.2.4
13. Linux Kernel-2.6.x (用GCC-3.0 以上版本编译的)
14. Make-3.79.1
15. Patch-2.5.4
16. Sed-3.0.2
17. Tar-1.14

LFS 6.3 中提供了检查宿主系统以上工具版本号的脚本,不过它只会打印系统的版本号,你还需要自己去检查各个版本号是否满足要求。这里我提供了一个可以直接比较版本号是否满足要求的脚本。脚本内容如下:

#!/bin/bash

function check_version() {
    local need_version=$1
    local install_version=$2
    local back='\e[0m'
    local red='\e[1;31m'
    local green='\e[1;32m'

    if [ "$install_version" = "$need_version" ]; then
        echo -e "\tinstall: $install_version$green\t[MATCH]$back"
    else
        if [[ "$install_version" > "$need_version" ]]; then
            echo -e "\tinstall: $install_version$green\t[OK]$back"
        else
            echo -e "\tinstall: $install_version$red\t[FAILED]$back"
        fi
    fi
}

function check_package() {
    local name=$1
    echo -n "check $1..."
    local cmd=$2
    local need_version=$(echo $name | cut -d'-' -f2)
    local ver_length=$(echo $need_version | tr -cd '.' | wc -c)
    if [ "$ver_length" = 1 ]; then
       check_version "$need_version" $($cmd | grep -o '[0-9]\+\.[0-9]\+')
    else
       check_version "$need_version" $($cmd | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+')
    fi
}

function check_pack(){
    check_package "$1" "$2 --version"
}

check_pack 'Bash-2.05a' 'bash'
check_pack 'Binutils-2.12' 'ld'
check_pack 'Bison-1.875' 'bison'
bzip2 --version  2>&1 < /dev/null | head -n1 > bzip.version
check_package 'Bzip2-1.0.2' 'cat bzip.version'
rm bzip.version
check_pack 'Coreutils-5.0' 'chown'
check_pack 'Diffutils-2.8' 'diff'
check_pack 'Findutils-4.1.20' 'find'
check_pack 'Gawk-3.0' 'gawk'
check_pack 'Gcc-3.0.1' 'gcc'
check_package 'Glibc-2.2.5' '/lib/libc.so.6'
check_pack 'Grep-2.5' 'grep'
check_pack 'Gzip-1.2.4' 'gzip'
check_package 'Linux Kernel-2.6' 'cat /proc/version'
check_pack 'Make-3.79' 'make'
check_pack 'Patch-2.5.4' 'patch'
check_pack 'Sed-3.0.2' 'sed'
check_pack 'Tar-1.14' 'tar'

如果知道如何运行脚本,可以自行编辑这个文件来运行,如果不熟悉可以用按照以下步骤来运行:

root[~]# wget http://www.adintr.com/media/tools/lfs_check_host_6.3.sh.txt -O host_check.sh
root[~]# source host_check.sh

如果一切正常的话你会看到类似如下的输出:

提示 MATCH 表示版本匹配正确,OK 的表示已经安装的版本号大于需要的版本号,如果出现 FAILED,你就需要先更新相应的软件包了。

1.7 硬盘分区

根据 LFS 的建议,我们把硬盘分为 4 个区:第一个 /boot 分区,大小为 1G,用于放置启动系统所需的文件,尽量小一些,这样启动速度会更快;第二个 / 根分区,大小为 40G,存放系统的根目录;第四个 swap 分区,大小为 4 G,是操作系统用来作为虚拟内存的;最后分第三个 /usr/src,使用剩余的所有空间,用来存放源代码。由于硬盘最多可以有 4 个主分区,所以我们把所有分区都分为主分区。

要点指示 4:主分区,扩展分区,逻辑分区

硬盘的主引导记录(MBR,Master Boot Record)是硬盘中的第一个扇区,总共 512 个字节,其中引导程序使用了 446 个字节,另外的 64 个字节交给了硬盘分区表(DPT,Disk Partition Table)。 这 64 个字节容量很小,最多只能记录 4 个分区,这样直接记录在 MBR分区表中的分区就是主分区。所以,一块硬盘最多只能有 4 个主分区。

为了让硬盘能分更多的区,可以把这 4 个主分区中的一部分作为扩展分区,扩展分区并不能直接使用,它是容纳其它分区的一个容器,在这样的情况下,主分区加扩展分区的总数不超过 4 个。

对于每一个扩展分区,在它开始位置的第一个扇区里,可以使用类似硬盘 MBR 的方法来再次建立分区表,不过它的大小可以比 MBR 上的 DPT 大。这样建立在扩展分区的分区表上的分区叫做逻辑分区,一个扩展分区最多可以包含多个逻辑分区,其数量不受 4 个的限制。

下面我们开始进行分区操作。用于分区的软件很多,这里以命令行下的 fdisk为例,使用其他你熟悉的分区工具也是完全可以的。使用 ssh 登陆到 LiveCD 启动的虚拟主机中,用 fdisk -l 命令可以查看当前的分区情况,如果硬盘还没有分区,输出是类似于下面这种形式的:

root [ ~ ]# fdisk -l

Disk /dev/sda: 85.8 GB, 85899345920 bytes
255 heads, 63 sectors/track, 10443 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Disk /dev/sda doesn't contain a valid partition table

注意硬盘厂商计算硬盘容量的方法和通常使用表示容量的方法不同,一般情况下,我们的使用习惯为: 1T = 1024G,1G=1024M,1M=1024K,1K=1024Byte,1Byte=8Bit。而硬盘厂商使用的容量为:1T=1000G,1G=1000M,1M=1000K,1K=1000Byte,1Byte=8Bit。所以我们这里看到的容量和我们刚刚创建虚拟机时输入的容量会有些出入。输入 fdisk /dev/sda 命令,进入 fdisk 的命令提示符:

root [ ~ ]# fdisk /dev/sda
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that, of course, the previous
content won't be recoverable.


The number of cylinders for this disk is set to 10443.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help):

输入 m 可以查看帮助,列出可以使用的命令列表。n 创建分区,a 设置启动分区,p显示分区列表,w写入分区后退出。分区过程如下,由于这里的输入很多单个字母的命令,所以特别把输入用黄色来表示,方便区分:

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-10443, default 1):
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-10443, default 10443): +1G

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (124-10443, default 124):
Using default value 124
Last cylinder or +size or +sizeM or +sizeK (124-10443, default 10443): +40G

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 3
First cylinder (4988-10443, default 4988):
Using default value 4988
Last cylinder or +size or +sizeM or +sizeK (4988-10443, default 10443): +40G

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Selected partition 4
First cylinder (9852-10443, default 9852):
Using default value 9852
Last cylinder or +size or +sizeM or +sizeK (9852-10443, default 10443):
Using default value 10443

Command (m for help): a
Partition number (1-4): 1

Command (m for help): p

Disk /dev/sda: 85.8 GB, 85899345920 bytes
255 heads, 63 sectors/track, 10443 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1         123      987966   83  Linux
/dev/sda2             124        4987    39070080   83  Linux
/dev/sda3            4988        9851    39070080   83  Linux
/dev/sda4            9852       10443     4755240   83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
root [ ~ ]#  

到此,硬盘就已经分好区了,你可以再次使用 fdisk -l 命令来查看现在的分区情况。接下来我们将对分区进行格式化,我们将前面三个分区格式话成 ext3 格式,最后一个分区格式化成 swap 格式:

root [ ~ ]# mke2fs -jv /dev/sda1
...
root [ ~ ]# mke2fs -jv /dev/sda2
...
root [ ~ ]# mke2fs -jv /dev/sda3
...
root [ ~ ]# mkswap /dev/sda4
...

最后,为了能够在系统上访问这些分区,我们需要挂载这些分区,挂载之前我们先创建一个目录 /mnt/lfs,并且设置一个环境变量 LFS=/mnt/lfs。

root [ ~ ]# mkdir /mnt/lfs
root [ ~ ]# export LFS=/mnt/lfs

由于我们是用 ssh 登陆系统来使用的,创建的环境变量在 ssh 会话退出后就会消失,所以我们需要把 export LFS=/mnt/lfs 这个命令放到一个登陆时自动执行的脚本中 ~/.bash_login。如果你熟悉某种文本编辑器(比如 vi),可以直接编辑这个文件为:

如果不熟悉 Linux 的文本编辑器,可以用下面这个命令来完成:

root [ ~ ]# echo -e 'export LFS=/mnt/lfs\necho "LFS=$LFS"' > ~/.bash_login

这个命令使用 echo 回显字符串,-e 参数可以让 \n 被替换成换行符,最后通过输出重定向把回显的内容重定位到文件 ~/.bash_login。这样,每当我们登陆的时候这个变量就会自动设置好了,并给出一个提示:

要点指示 5:环境变量

环境变量是操作系统广泛支持的一种技术,它是一个具有特定名字的对象。环境变量可以 用于系统的配置,也可以用于父进程向子进程传递信息。CGI 就是通过环境变量的方式来把表单信息从 Web 服务器传递给 CGI 程序的。Linux 的环境变量和 Windows 的环境变量基本相同,区别在于 Linux 使用 $ 前缀来表示变量,而 Windows 使用前后缀的 % 来表示。

Linux 系统中比较重要的环境变量有:

$PATH Shell 搜索可执行命令的路径,注意它通常不包括当前目录,用 :分隔;
$LANG 当前系统语言;
$PWD 当前目录;
$SHELL 当前的 Shell 程序;

在命令中可以直接使用环境变量,使用的时候它会被值替换后在执行命令。通过使用环境变量来记录常用的值或是命令的中间结果可以让命令简化。

要点指示 6:输入输出重定向

在之前的管道中我们提到过,Shell 在执行命令时会自动为程序打开三个句柄:标准输入,标准输出,标准错误输出。它们的默认值是键盘和虚拟终端,通过使用重定向的方法,我们可以让 Shell 打开 3 个文件的句柄来做为程序的输入和输出句柄。这样程序将自动获得文件内容作为输入,也可以把输出保存到一个文件里面。

重定向标准输入的方法是:command < filename;
重定向标准输出的方法是:command > filename;
重定向错误输出的方法是:command 2>filename;

另外可以把 > 替换成 >>,这样 Shell 将会用追加的方式打开文件,然后输出的内容会增加到文件的末尾,而不会替换掉文件原来的内容。

使用输入输出重定向来创建和修改文件是 Linux 下的常用操作,对于内容比较少的文件,他比使用编辑器来编辑文件更加方便;更重要的是,它可以把文件的创建和修改操作放到脚本里面去自动执行,如果使用编辑器,要在脚本里面控制它来创建或修改文件是非常麻烦的。

下面我们开始挂载我们的分区:

root [ ~ ]# mount -v -t ext3 /dev/sda2 $LFS
/dev/sda2 on /mnt/lfs type ext3 (rw)
root [ ~ ]# mkdir -pv $LFS{/boot,/usr/src}
mkdir: created directory `/mnt/lfs/boot'
mkdir: created directory `/mnt/lfs/usr'
mkdir: created directory `/mnt/lfs/usr/src'
root [ ~ ]# mount -v -t ext3 /dev/sda1 $LFS/boot
/dev/sda1 on /mnt/lfs/boot type ext3 (rw)
root [ ~ ]# mount -v -t ext3 /dev/sda3 $LFS/usr/src
/dev/sda3 on /mnt/lfs/usr/src type ext3 (rw)
root [ ~ ]# /sbin/swapon -v /dev/sda4
swapon on /dev/sda4

其中,mount 命令用于挂载文件系统,-t 指明了文件系统的类型,-v 是大多数的 linux 命令都支持的一个参数,它让命令打印出所作的操作,最后是挂载的设备名和挂载到的位置。在命令中我们还使用了之前创建的环境变量 $LFS,在执行时它会被替换成它的值 /mnt/lfs。根分区挂载好了后,我们在根分区下建立了两个目录 boot 和 usr/src 用于挂载我们之前的 /boot 和 /usr/src 分区。创建目录时我们使用了 -p 参数,它可以在上层目录不存在时自动创建上层目录,而不是提示错误。随后使用的 $LFS{/boot,/usr/src} 是一种 bash shell 的扩展,{} 里的部分会被展开,这个命令等价于: mkdir -pv $LFS/boot $LFS/usr/src。这种方式在创建大量的目录时会非常有用,之后还会遇到。最后 swapon 命令让系统使用指定的分区来作为交换分区,使用 swapoff 可以关闭交换分区。

到此,我们用于安装系统的硬盘就已经准备好了。我们可以使用 df 命令来查看挂载的分区情况,加 -h 参数可以让分区大小以 K/M/G 这种更人性化的方式来显示:

1.8 配置环境

在开始编译源代码之前,我们还有一些最后的准备工作要做。首先,我们将源代码从光盘拷贝到硬盘上,由于之前我们已经将硬盘挂载到了 /mnt/lfs 上面了,所以:

root [ ~ ]# mkdir -v $LFS/sources
mkdir: created directory `/mnt/lfs/sources'
root [ ~ ]# chmod -v a+wt $LFS/sources
mode of `/mnt/lfs/sources' changed to 1777 (rwxrwxrwt)
root [ ~ ]# cp /lfs-sources/* $LFS/sources/

其中 chmod 是改变文件权限的命令,这里创建完 $LFS/sources 目录后把它的权限改为所有人都可以写的,我们之后的工作基本都要在这个目录下进行。cp 命令是拷贝文件的命令,之前已经提到过光盘里已经包含了所需要的源代码包,放在 /lfs-sources 目录下,所以我们把它拷贝到我们的工作目录 $LFS/sources 里。

编译正式系统之前,我们会先编译一套工具,我们现在就创建好存放这些工具的目录:

root [ ~ ]# mkdir -v $LFS/tools
mkdir: created directory `/mnt/lfs/tools'
root [ ~ ]# ln -sv $LFS/tools /
`/tools' -> `/mnt/lfs/tools'

其中 ln 是创建符号链接的命令,-s 选项指明了是软连接,软连接大致相当于 windows 下的快捷方式。

要点指示 7:链接

在文件系统里,文件或目录的内容存储在一些块集合中。而有关文件的信息则包含在一个结点的结构中,这个结构记录的信息包括所有者、上次访问文件的时间、文件的大小、它是否是一个目录,以及如何读写他的内容等等。结点的编号被称为文件序列号,在特定文件系统内是惟一的。一个目录的内容就是名称和结点编号的集合。

链接允许同一文件或目录有多个名称。一个硬链接就是一个新的名称和已经存在的结点编号组成的一个新条目。

软链接或符号链接则是一个新的名称和新的结点组成的,结点的内容指向了另外的一个目录条目。

只能对文件才能创建硬链接,目录是不能创建硬链接的(. 和 .. 是特例)。不同的文件系统之间也不能创建硬链接。如果一个文件有多个硬链接,只有当所有的硬链接都删除后文件内容才会被删除。

软链接由于只是指向另一个文件或目录,它有自己的结点结构,所以会宽松许多:它可以对目录创建;可以对不存在的文件创建;可以跨越文件系统。删除一个软链接不会删除目标文件或目录,删除目标文件或目录也不会删除软链接。

我们现在是以 root 帐号登陆的系统,这是非常危险的,一个错误的操作可能摧毁系统,不当的操作可能会造成安全隐患。在 linux 下,通常的操作都应该以普通的用户来进行,所以,我们创建一个用来完成编译工作的用户:

root [ ~ ]# groupadd lfs
root [ ~ ]# useradd -s /bin/bash -g lfs -m -k /dev/null lfs
root [ ~ ]# passwd lfs
Changing password for lfs
Enter the new password (minimum of 5, maximum of 127 characters)
Please use a combination of upper and lower case letters and numbers.
New password:
Re-enter new password:
Password changed.
root [ ~ ]# chown -v lfs $LFS/tools
changed ownership of `/mnt/lfs/tools' to lfs
root [ ~ ]# chown -v lfs $LFS/sources
changed ownership of `/mnt/lfs/sources' to lfs
root [ ~ ]# su - lfs
lfs [ ~ ]$  

groupadd 命令创建了一个 lfs 的用户组。之后的 useradd 用于创建用户,参数包括:

-s /bin/bash: 指定 bash 为 lfs 用户的默认 shell。
-g lfs: 该选项将 lfs 用户添加到 lfs 组。
-m: 该选项为 lfs 用户创建 home 目录。
-k /dev/null: 这个参数通过将输入位置修改为特殊的空设备来防止从框架目录(默认是 /etc/skel) 拷贝文件。

lfs 这是所创建的组和用户的实际名字

随后的 passwd lfs 用于设置 lfs 用户的密码,然后用 chown 把 $LFS/tools 和 $LFS/sources 目录的所有者设置为 lfs 用户。最后,su 命令用于切换用户,"-" 指示开启一个登陆 Shell。切换用户后我们看到,命令提示符从红色变成了绿色。

下面我们要创建两个脚本来设置工作的环境变量,第一个 ~/.bash_profile 是用户登陆时自动执行的,我们创建并编译这个文件为:

exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash

文件中的这个命令让在用户登陆时用一个全新的环境来取代当前的环境,只继承了其中的 HOME, TERM, PS1 等变量,这样可以减少宿主系统编译环境的影响,保证工作环境干净。

另一个脚本是 ~/.bashrc 文件,一个非登陆的 shell 启动时会自动运行这个脚本文件,编辑这个文件的内容为:

set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
PATH=/tools/bin:/bin:/usr/bin
export LFS LC_ALL PATH

set +h 关闭了 bash 的 hash 功能。这样强制每次执行的命令都到 $PATH 路径中进行搜索。当我们编译出来一个新工具后,我们希望随后用到这个工具的时候就使用我们自己编译的版本,不再使用宿主系统的了。

umask 设置了创建文件和目录时的默认权限,022 让所有者可写,其他用户可以读取和执行。

随后我们设置了一些环境变量:LFS 是我们的系统的挂载点;LC_ALL 设置了本地语言环境,务必确保其值为 "POSIX" 或 "C";PATH 变量把我们编译的工具目录 /tools/bin 放在最前面,结合 +h 让我们的程序安装好了以后可以立即替换掉宿主系统版本。

要点指示 8:编辑文件

UNIX 下几乎所有的配置都是以文本文件的形式出现的,所以一个掌握一个编辑文本文件的工具是非常重要的。vim 是一个常用的在命令行下的全屏文本编辑器,它功能非常强大,甚至一些软件开发者都使用它来编辑源代码。

vi 有两种模式,一种是命令模式,一种是编辑模式(包括插入和覆盖)。命令模式下的输入都会作为命令解析,不会进入到编辑的文本中;在编辑模式下的输入会做为文本的一部分。

打开 vi 后首先进入的是命令模式,使用 i 或 a 或 Insert 即可进入编辑模式,再次使用 Insert 可以在插入和贴换之间进行切换。在编辑模式下使用 ESC 键可以进入命令模式。

在命令模式下常用的命令包括:

:w 保存;
:wq 保存并退出;
:q 退出;
:q! 强制退出,即使有修改没有保存;
dd 删除光标所在行;
/ 搜索文本
n 搜索下一个

更多的命令和使用方法请参考:http://www.adintr.com/article/linux_vi_command.html

退出 ssh 连接,重新连接并使用 lfs 帐号登陆系统,然后执行 echo $LFS, echo $PATH,确保其输出如下图所示,这表明上述脚本已经生效。

   上一章   回目录   下一章   

▲评论

› 网友 qq:2396253356 () 于 2013-11-18 20:24:49 发表评论说:

你好!我看了你做的lfs的pdf文档--感觉很不错,很好操作
我按照你的文档进行了lfs但是遇到了些问题希望能得到你的帮助
但在最后启动时遇到了问题--显示的错误时---
显示的错误是:
list of all partitions:
no filesystem could mount root, tride:
kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
----
整个操作中出现的异常情况总结:
<1>
grub设置完成后显示proble if bios ..this may take a long time
<2>启动前的logout之后进行的
umount $LFS操作,
操作不成功显示信息是---
device is busy could not 。。。
然后我用了fuser -u -v -k $LFS
杀掉了进程----umount成功了启动后--就遇到了上面的情况
其他的操作都没有出现问题
不知道是哪里出了问题----
后来我想是不是我编译内核是出了问题没支持到SICI不过我不太懂那个配置-
于是试了一下IDE的方式--也不成功--过程中出现的错误和异常还是一模一样!!
---
环境是在---win7的vm上
---
google了好多找不到头绪,希望你能帮助我--
我的联系方式是:
qq:2396253356
gmail:stu120131227@gmail.com
拜托了!!

› 网友 qq:2396253356 (email:stu120131227@gmail.com; work:学生; ) 于 2013-11-18 20:41:19 发表评论说:

bios的那个异常信息具体一下(probing devices to guess BIOS drives.This my take a long time.)putty上操作玩才会显示
大概意思是
qq:2396253356

X 正在回复:
姓 名: 留下更多信息
性 别:
邮 件:
主 页:
Q Q:
来 自:
职 业:
评 论:
验 证:


Valid HTML 4.01 Strict Valid CSS!
Copyleft.A!die Software Studio.ADSS
Power by webmaster@adintr.com