在第一部分,我们编译了一个工具链及临时系统,然后在第二部分我们chroot到/mnt/lfs下面,利用临时系统的工具编译了我们最终的LFS系统。不过此时,我们的LFS系统还是不完整的,因为我们还没有安装LFS的内核和引导程序,同时系统的引导脚本和一些必要的配置文件也都还没有配置。这一部分我们就来解决这些问题。

首先,进入chroot环境:

1 chroot "$LFS" /usr/bin/env -i \
2         HOME=/root TERM="$TERM" PS1="\$? \u:\w\$ " \
3         PATH=/bin:/usr/bin:/sbin:/usr/sbin \
4         /bin/bash --login

 

1.配置网卡

  • 创建网卡的固定名称

如果你的系统上只有一个网卡,这一步似乎没什么用处。不过对于我,台式机上有一个有线网卡和无线网卡,就不得不配置了。关于为什么要创建固定的网卡名称,是因为Udev和模块化的网络驱动,导致系统每次重新启动时识别网卡的顺序不固定,就可能导致网卡1的名称是eth0,网卡2的名称是eth1,而在另一次的启动时是网卡1的名称是eth1,而网卡2的名称是eth0。因此,Udev的配置文件是由MAC地址将网卡对应到固定的名称的。而这个配置文件在我们第2部分安装Udev软件包时已经生成了,文件名是/etc/udev/rules.d/70-persistent-net.rules

此配置文件的关键字及其解释如下:

  1. SUBSYSTEM=="net" — 此项告诉 Udev 忽略不是网卡的设备。
  2. ACTION=="add" — 此项告诉 Udev 对于非添加的 uevent ("移除" 和 "改变" 这两个 uevents 也会发生,但是无需重命名网络接口) 忽略此规则。
  3. DRIVERS=="?*" — 此项存在时 Udev 会忽略 VLAN 或者子接口 (因为子接口没有驱动)。这些子接口要跳过是为了防止名称与其父设备冲突。
  4. ATTR{address} — 此关键字的值是 NIC 的 MAC 地址。
  5. ATTR{type}=="1" — 此项确保此规则对于某些创建多个虚拟接口的无线驱动只匹配首要接口。跳过次要接口的原因和 VLAN 以及子接口的原因相同:若不如此会出现冲突。
  6. KERNEL=="eth*" — 此关键字添加到 Udev 规则创建器以处理具有多个网络接口而且有相同的 MAC地址的情况 (例如 PS3).如果独立的接口有不同的基础名称,此关键字就将允许 Udev 区分它们。对于多数 LFS 用户而言此项并不必须然而无害。
  7. NAME — 此关键字的值是 Udev 将会给此接口分配的名称

NAME 的值是最重要的部分,配置下面的文件时使用此NAME值。这个配置文件一般会自动生成,只需要根据情况修改一下就可以了。下图是我的配置情况,仅供参考。我的是自动生成的,并且复合我的实际情况,所以就不用再修改了,直接使用。

cdlinux能运行在arm架构吗 cdlinux支持什么网卡_运行级别

  • 创建网卡的配置文件

网络脚本开关的接口取决于 /etc/sysconfig/ 中的文件。要配置的每个网卡接口在此目录中都应该有一个文件,例如 ifconfig.xyz,其中 “xyz” 应该是一个对管理员有意义的名称,如设备名 (比如eth0)。此文件中是该网卡接口的属性,例如 IP 地址、子网掩码等。文件名的主干必须是 ifconfig。

以下命令会创建一个样例文件,给 eth0 设备分配一个静态 IP 地址:

1 cd /etc/sysconfig/
 2 cat > ifconfig.eth0 << "EOF"
 3 ONBOOT=yes
 4 IFACE=eth0
 5 SERVICE=ipv4-static
 6 IP=192.168.1.1
 7 GATEWAY=192.168.1.2
 8 PREFIX=24
 9 BROADCAST=192.168.1.255
10 EOF

如果 ONBOOT 变量设置为 “yes”,引导脚本中的网络脚本会在系统引导时打开该 NIC,否则网络脚本就会忽略之并且不会自动打开该 NIC。该接口可以使用 ifup 和 ifdown 命令来手动打开和关闭
IFACE 变量定义网卡接口名称,例如 eth0。所有的网络设备配置文件都需要它。这个名称就是上一步中配置的NAME值
SERVICE 变量定义获取 IP 地址的方法。LFS-Bootscripts 程序包有一个模块化的 IP 对应方法,在 /lib/services/ 目录中创建额外文件可以允许其他的 IP 对应directory allows other IP 对应方法。此项经常用于 DHCP,在 BLFS 中提到。
如果有网关,GATEWAY 变量应该包含默认网关的 IP 地址,否则注释掉这整个变量。
PREFIX 变量包含子网使用的位数。IP 地址中有 4 个 8 位组。如果子网的掩码是 255.255.255.0,它就使用前 3 个 8 位组指定网络号。如果子网掩码是 255.255.255.240,使用的就是前 28 位。超过 24 位的前缀通常被 DSL 和基于线电缆的 ISP 使用。这一例子 (PREFIX=24) 中,子网掩码是 255.255.255.0。根据你的子网调节 PREFIX 变量的值。如果忽略,其默认值为24。
要获取更多信息,请参考 ifup 的手册页。

  • 创建 /etc/resolv.conf文件

如果你的系统要连接到互联网,它需要一种 DNS 名称解析服务来解析互联网域名和 IP 地址,反之亦然。最佳实现方式是将 DNS 服务器的 IP 地址 (从 ISP 或者网络管理员处获取) 置于 /etc/resolv.conf 中。运行以下命令创建此文件:

1 cat > /etc/resolv.conf << "EOF"
2 # Begin /etc/resolv.conf
3 domain <domain>
4 nameserver <address>
5 nameserver <address>
6 # End /etc/resolv.conf
7 EOF

domain 声明可以忽略或者以 search 声明替换。参考 resolv.conf 的手册页获取更多细节。
将 <address> 替换为最适合的 DNS 的 IP 地址。经常会有超过一个条目 (要求备选服务器有相关兼容性)。如果你只想要一个 DNS 服务器,移除文件中 nameserver 的第二行。该 IP 地址可以是本地网络上
的一台路由器。谷歌公开 IPv4 DNS 地址为 8.8.8.8 和 8.8.4.4。
这三处设置好之后,网卡也就基本配置完了。

2. 配置 /etc/hosts 文件
如果要配置网卡,那么就要在 /etc/hosts 文件中决定 IP 地址、FQDN 和可能使用的别名的对应关系。语法是:

IP_address myhost.example.org aliases

运行以下命令创建 /etc/hosts 文件:

1 cat > /etc/hosts << "EOF"
2 # Begin /etc/hosts (network card version)
3 127.0.0.1 localhost
4 <192.168.1.1> <HOSTNAME.example.org> [alias1] [alias2 ...]
5 # End /etc/hosts (network card version)
6 EOF

<192.168.1.1> 和 <HOSTNAME.example.org> 的值应该按照指定的用途或者需求进行修改 可选的对应名称可以忽略。确定IP地址在私有IP地址区间内,除非你有 申请的域名。
如果不配置网卡,运行以下命令创建 /etc/hosts 文件:

1 cat > /etc/hosts << "EOF"
2 # Begin /etc/hosts (no network card version)
3 127.0.0.1 <HOSTNAME.example.org> <HOSTNAME> localhost
4 # End /etc/hosts (no network card version)
5 EOF

下图是我的/etc/hosts配置,仅供参考

cdlinux能运行在arm架构吗 cdlinux支持什么网卡_IP_02

3. LFS系统上的设备和模块管理

这一部分的内容比较不容易理解,涉及到的硬件会比较多,感觉还是看英文原版比较好,毕竟翻译还是有一些“失真”的。对于第一次编译LFS的新手,没必要花费时间来配置这方面,可以略过。当对LFS比较熟悉的时候,再回过头来配置设备。

sysfs 文件系统 http://www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf
一种用户空间下 devfs 的实现 http://www.kroah.com/linux/talks/ols_2003_udev_paper/Reprint-Kroah-Hartman-OLS2003.pdf
LFS7.4book Device and Module Handling on an LFS System http://www.linuxfromscratch.org/lfs/view/7.4/chapter07/udev.html4.

4. LFS-Bootscripts-20130821
LFS-Bootscripts 程序包包含一组脚本用于在引导/关机时启动/停止 LFS 系统。
安装引导脚本LFS-Bootscripts:

1 tar xvf lfs-bootscripts-20130821.tar.bz2
2 cd lfs-bootscripts-20130821
3 make install
4 cd ..
5 rm -rf lfs-bootscripts-20130821

Linux 使用一种特殊的基于“运行级”的引导工具,名为 SysVinit,SysVinit (以下简称 “init”) 使用运行级别的方式工作。有 7 种 (编号为 0 到 6) 运行级别 (其实有更多,但只用于特殊情况,通常并不使用。更多细节参见 init(8)),每个都对应计算机在它启动时要进行的动作。默认运行级别为 3。以下列出不同运行级别实现的描述:

0:关闭计算机
1:单用户模式
2:不带网络的多用户模式
3:带网络的多用户模式
4:保留,用于自定义,否则与 3 相同
5:与 4 相同,但通常用于 GUI 登录 (如 X 的 xdm 或者 KDE 的 kdm)
6:重新引导计算机

在内核初始化过程中,第一个运行的程序要么是在命令行中指定的,要么就是默认的 init。此程序需要读取初始化文件/etc/inittab。用下面的命令创建之:

cat > /etc/inittab << "EOF"
# Begin /etc/inittab
id:3:initdefault:

si::sysinit:/etc/rc.d/init.d/rc S

l0:0:wait:/etc/rc.d/init.d/rc 0
l1:S1:wait:/etc/rc.d/init.d/rc 1
l2:2:wait:/etc/rc.d/init.d/rc 2
l3:3:wait:/etc/rc.d/init.d/rc 3
l4:4:wait:/etc/rc.d/init.d/rc 4
l5:5:wait:/etc/rc.d/init.d/rc 5
l6:6:wait:/etc/rc.d/init.d/rc 6

ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

su:S016:once:/sbin/sulogin

1:2345:respawn:/sbin/agetty --noclear tty1 9600
2:2345:respawn:/sbin/agetty tty2 9600
3:2345:respawn:/sbin/agetty tty3 9600
4:2345:respawn:/sbin/agetty tty4 9600
5:2345:respawn:/sbin/agetty tty5 9600
6:2345:respawn:/sbin/agetty tty6 9600
# End /etc/inittab
EOF

对此文件的解释位于 inittab 的手册页中。

对于 LFS,运行的核心命令是 rc。以上的初始化文件将会要求rc 运行 /etc/rc.d/rcsysinit.d 目录中所有以 S 开头的脚本,然后是 /etc/rc.d/rc?.d 目录中所有以 S 开头的脚本,其中问号由 initdefault 的值指定。
出于方便考虑,rc 脚本读取 /lib/lsb/init-functions 中的功能库。此库还读取可选的配置文件 /etc/sysconfig/rc.site。之前几节中描述的任何系统配置文件参数都可以置于此文件中,使得所有的系统参数合并在这一个文件中。出于调试方便考虑,功能脚本还将所有输出以日志的形式记录于 /run/var/bootlog 中。由于 /run目录是一个 tmpfs,此文件在重新引导过后不会保留,然而它在引导结束时会被附加到一个更稳定的文件 /var/log/boot.log 之后。

改变运行级别通过 init <level> 完成,其中 <level> 就是目标运行级别了。例如要重新引导计算机,用户可以执行 init 6 命令,也就是 reboot 命令的别名。相似地, init 0 也是 halt 的别名。
在 /etc/rc.d 和 rcsysinit.d 中有一些与 rc?.d 相似的目录 (其中问号是运行级别号码),都包含一些符号链接,有些以 K 开头,其他的以 S 开头,在开头字母之后都有两位数字。K 代表停止 (kill) 服务,S 代表开始服务。数字表示脚本的运行顺序,从 00 到 99——数字越小执行越早。当 init 切换至另一个运行级别时,对应的服务就会开始或者停止,这取决于选定的运行级别。真实的脚本位于 /etc/rc.d/init.d。它们完成实际工作,符号链接也指向它们。K 链接和 S 链接都指向/etc/rc.d/init.d中的同一个脚本,这是因为这些脚本可以带有start、stop、restart、reload 和 status 这些参数调用。当遇到 K 的时候,对应的脚本被带stop 参数调用。当遇到 S 的时候,对应的脚本被带 start 参数调用。这个解释有一个例外。在 rc0.d 和 rc6.d 中的以 S 开头的链接不会开始任何服务。他们会以stop 参数调用,来停止服务。它背后的逻辑是用户要重新引导或者关闭系统,没有什么需要开始的,系统正要终止。
你可以自由修改引导脚本工作的方式

5. 配置系统主机名
localnet 脚本的部分工作就是设置系统的主机名。它需要在 /etc/sysconfig/network 文件中配置。
创建 /etc/sysconfig/network 文件并输入一个主机名,运行:

echo "HOSTNAME=lfs-desktop" > /etc/sysconfig/network

<lfs> 应改为计算机名。不要在此处输入 FDQN,该信息应存入 /etc/hosts 文件。

6. 配置setclock 脚本
setclock脚本从硬件时钟,也就是 BIOS 或 CMOS 时钟读取时间。如果硬件时钟设置为 UTC ,这个脚本会使用 /etc/localtime 文件(这个文件把用户所在的时区告诉 hwclock 程序)将硬件时钟的时间转换为本地时间。因为没有办法自动检测硬件时钟是否设置为 UTC 时间,因此需要手动设置这一项。
如果您忘了硬件时钟是不是设置为 UTC 时间了,可以运行 hwclock --localtime --show 命令,这将显示硬件时钟当前的时间。如果显示的时间符合您的手表的时间,那么硬件时钟设置的是本地时间;如果 hwclock 显示的不是本地时间,就有可能设置的是 UTC 时间,可以通过在所显示的 hwclock 时间加上或减去您所在时区的小时数来验证。例如,位于中国大陆的 GMT +0800 时区的用户应该将 hwclock 的输出减去 8 小时。
如果你的硬件使用的不是 UTC 时间,就必须将下面的 UTC 变量值设为 0 (零),而"UTC=1"表示使用的是UTC时间。运行下面的命令新建一个 /etc/sysconfig/clock

1 cat > /etc/sysconfig/clock << "EOF"
2 # Begin /etc/sysconfig/clock
3 UTC=0
4 # Set this to any options you might need to give to hwclock,
5 # such as machine hardware clock type for Alphas.
6 CLOCKPARAMS=
7 # End /etc/sysconfig/clock
8 EOF

 

7. 配置Linux控制台
本节讨论如何配置 console 初始化脚本来设置键盘映射表和控制台字体。如果您不使用非 ASCII 字符(英镑和欧元符号就是非 ASCII 字符的例子),并且是美式键盘,可以跳过这一节,没有配置文件的话,console

console 使用 /etc/sysconfig/console 作为配置文件以决定使用什么键盘映射表和屏幕字体,不过对于中文、日文、韩文等一些语言,Linux 的控制台不能显示需要的字符。这些语种的用户应当安装 X Window 系统,包含所需字符集的字体,以及合适的输入法(例如,SCIM 支持很多语言)。这应该是BLFS的内容了。在这里就不配置了。具体可以参考http://www.tldp.org/HOWTO/Chinese-HOWTO.html

8. 配置sysklogd 脚本
sysklogd 脚本用 -m 0 选项调用 syslogd 程序,此选项关闭 syslogd 默认每 20 分钟对日志文件写入的周期性时间戳。如果你要打开这个周期性时间标记,编辑 /etc/sysconfig/rc.site 并且将SYSKLOGD_PARMS 变量调整为需要的值。例如,把这个变量设置为空值会删除所有的参数(SYSKLOGD_PARMS=)
请运行 man syslogd 以获得更多信息。

9. rc.site 文件(可选)

这个文件实际上是一个综合的配置文件,它包含启动脚本所有的设置,同时它还可以指定/etc/sysconfig/目录下的hostname,console和clock文件中的变量的值。如果关联的变量在这些独立的文件和 rc.site 中都存在,以rc.site指定的为准。
rc.site 还包括可以自定义引导进程其他方面的参数。设置 IPROMPT 变量会启用引导脚本的选择性运行。其他选项在文件中的注释有介绍。此文件的默认版本如下:

1 # rc.site
 2 # Optional parameters for boot scripts.
 3 
 4 # Distro Information
 5 # These values, if specified here, override the defaults
 6 #DISTRO="Linux From Scratch" # The distro name
 7 #DISTRO_CONTACT="lfs-dev@linuxfromscratch.org" # Bug report address
 8 #DISTRO_MINI="LFS" # Short name used in filenames for distro config
 9 
10 # Define custom colors used in messages printed to the screen
11 
12 # Please consult `man console_codes` for more information
13 # under the "ECMA-48 Set Graphics Rendition" section
14 #
15 # Warning: when switching from a 8bit to a 9bit font,
16 # the linux console will reinterpret the bold (1;) to
17 # the top 256 glyphs of the 9bit font. This does
18 # not affect framebuffer consoles
19 
20 # These values, if specified here, override the defaults
21 #BRACKET="\\033[1;34m" # Blue
22 #FAILURE="\\033[1;31m" # Red
23 #INFO="\\033[1;36m" # Cyan
24 #NORMAL="\\033[0;39m" # Grey
25 #SUCCESS="\\033[1;32m" # Green
26 #WARNING="\\033[1;33m" # Yellow
27 
28 # Use a colored prefix
29 # These values, if specified here, override the defaults
30 #BMPREFIX=" "
31 #SUCCESS_PREFIX="${SUCCESS} * ${NORMAL}"
32 #FAILURE_PREFIX="${FAILURE}*****${NORMAL}"
33 #WARNING_PREFIX="${WARNING} *** ${NORMAL}"
34 
35 # Interactive startup
36 #IPROMPT="yes" # Whether to display the interactive boot prompt
37 #itime="3" # The amount of time (in seconds) to display the prompt
38 
39 # The total length of the distro welcome string, without escape codes
40 #wlen=$(echo "Welcome to ${DISTRO}" | wc -c )
41 #welcome_message="Welcome to ${INFO}${DISTRO}${NORMAL}"
42 
43 # The total length of the interactive string, without escape codes
44 #ilen=$(echo "Press 'I' to enter interactive startup" | wc -c )
45 #i_message="Press '${FAILURE}I${NORMAL}' to enter interactive startup"
46 
47 # Set scripts to skip the file system check on reboot
48 #FASTBOOT=yes
49 
50 # Skip reading from the console
51 #HEADLESS=yes
52 
53 # Write out fsck progress if yes
54 #VERBOSE_FSCK=no
55 
56 # Speed up boot without waiting for settle in udev
57 #OMIT_UDEV_SETTLE=y
58 
59 # Speed up boot without waiting for settle in udev_retry
60 #OMIT_UDEV_RETRY_SETTLE=yes
61 
62 # Skip cleaning /tmp if yes
63 #SKIPTMPCLEAN=no
64 
65 # For setclock
66 #UTC=1
67 #CLOCKPARAMS=
68 
69 # For consolelog
70 #LOGLEVEL=5
71 
72 # For network
73 #HOSTNAME=mylfs
74 
75 # Delay between TERM and KILL signals at shutdown
76 #KILLDELAY=3
77 
78 # Optional sysklogd parameters
79 #SYSKLOGD_PARMS="-m 0"
80 
81 # Console parameters
82 #UNICODE=1
83 #KEYMAP="de-latin1"
84 #KEYMAP_CORRECTIONS="euro2"
85 #FONT="lat0-16 -m 8859-15"
86 #LEGACY_CHARSET=

自定义引导和关机脚本
LFS 引导脚本以比较高效的方式引导和关闭序同,但是你仍然可以在 rc.site 文件中进行几项调校使它更快或者按照你的喜好调节信息。要如此做,调节以上的 /etc/sysconfig/rc.site 文件。

  • 在引导脚本 udev 中调用了 udev settle,需要一定时间才能完成。这个时间是否需要取决于系统上出现的设备。如果你只有简单分区和一块以太网卡,引导进程可能就不必等待这一命令。要跳过之,设置变量 OMIT_UDEV_SETTLE=y。
  • 引导脚本 udev_retry 默认也会运行 udev settle。此命令只在 /var 目录独立挂载时必须。这是因为时钟需要 /var/lib/hwclock/adjtime 这个文件。其他的自定义可能也要等待 udev 完成,但是在很多安装副本中并不是必须的。要跳过此命令,设置变量 OMIT_UDEV_RETRY_SETTLE=y。
  • 文件系统检查默认是静默的。看起来是在引导过程中出现了一次延迟。要打开 fsck 的输出,设置变量 VERBOSE_FSCK=y。
  • 在重新引导过程中你可能会想要完全跳过文件系统检查,即 fsck。要如此做,要么创建文件 /fastboot,要么在重新引导系统时使用命令 /sbin/shutdown -f -r now。另一方面,你也可以强制检查所有的文件系统,创建 /forcefsck 或者运行 shutdown 时传递 -F 参数而不是 -f。设置变量 FASTBOOT=y 会在引导过程中禁用 fsck 直到被移除为止。不推荐长期如此。
  • 通常在 /tmp 目录中的所有文件在引导时都会删除。由于出现的文件或目录的数量不同,这一步会在引导过程中产生明显延迟。要跳过移除这些文件,设置变量 SKIPTMPCLEAN=y。
  • 在关机过程中 init 程序会给它启动的每个程序 (例如 agetty) 发送一个 TERM 信号,等待一个设置的时间 (默认 3 秒),然后给每个进程发送一个 KILL 信号并且再次等待。此进程在 sendsignals 中对于每个没有被自己的脚本关闭的程序循环进行。init 的延迟可以通过传递一个参数来设置。例如要移除init 的延迟,在关机护着重新引导时传递 -t0 参数 (如 /sbin/shutdown -t0 -r now)。sendsignals 脚本的延迟可以通过设置参数 KILLDELAY=0 来跳过。

10. Bash Shell 启动文件
shell 程序 /bin/bash (以下简称 “shell”) 使用一系列启动文件协助创建运行的环境。每个文件都有特定的用途,可能会以不同方式影响输入和交互环境。位于 /etc 目录中的文件提供全局设置。如果在主目录中有等价的文件,它可能会覆盖全局设置。使用 /bin/login 读取 /etc/passwd 文件成功登录后,启动了一个交互登录 shell 。用命令行可以启动一个交互非登录 shell(例如 [prompt]$/bin/bash)。非交互 shell 通常出现在 shell 脚本运行的时候,之所以称为非交互的,因为它正在运行一个脚本,而且命令与命令之间并不等待用户的输入。

要获得更多信息,请运行 info bash 以参考 Bash Startup Files and Interactive Shells

当以交互登录方式运行 shell 的时候,会读取 /etc/profile 和 ~/.bash_profile

下面是一个基本的 /etc/profile

  • 程序将产生翻译成本地语言的输出
  • 正确的将字符分类为字母、数字和其它类,这样做是必要的,可以让 bash
  • 为指定的国家设置正确的字母排序
  • 适当的默认页面大小
  • 为货币、时间和日期值设置正确的格式

运行一下命令创建/etc/profile 文件:

1 cat > /etc/profile << "EOF"
2 # Begin /etc/profile
3 
4 export LANG=zh_CN.UTF-8@euro
5 
6 # End /etc/profile
7 EOF

 

11. 创建 /etc/inputrc 文件
inputrc 文件为特定的情况处理键盘映射,这个文件被 Readline 用作启动文件,Readline 是 Bash 和其它大多数 shell 使用的与输入相关的库。
大多数人并不需要自定义键盘映射,所以下面的命令将创建一个适用于所有登陆用户的全局 /etc/inputrc 文件。如果你需要为某个用户覆盖默认的设置,你可以在该用户的主目录中创建一个包含自定义键盘映射的 .inputrc 文件。
要想了解更多关于如何编辑 inputrc 文件的信息,运行 info bash 以参考 bash 的 info 页的 Readline Init File 这一节,运行 info readline 以参考readline 自己的 info 页也不错。
下面是一个基本的全局 inputrc

1 cat > /etc/inputrc << "EOF"
 2 # Begin /etc/inputrc
 3 # Modified by Chris Lynn <roryo@roryo.dynup.net>
 4 
 5 # Allow the command prompt to wrap to the next line
 6 set horizontal-scroll-mode Off
 7 
 8 # Enable 8bit input
 9 set meta-flag On
10 set input-meta On
11 
12 # Turns off 8th bit stripping
13 set convert-meta Off
14 
15 # Keep the 8th bit for display
16 set output-meta On
17 
18 # none, visible or audible
19 set bell-style none
20 
21 # All of the following map the escape sequence of the value
22 # contained in the 1st argument to the readline specific functions
23 "\eOd": backward-word
24 "\eOc": forward-word
25 
26 # for linux console
27 "\e[1~": beginning-of-line
28 "\e[4~": end-of-line
29 "\e[5~": beginning-of-history
30 "\e[6~": end-of-history
31 "\e[3~": delete-char
32 "\e[2~": quoted-insert
33 
34 # for xterm
35 "\eOH": beginning-of-line
36 "\eOF": end-of-line
37 
38 # for Konsole
39 "\e[H": beginning-of-line
40 "\e[F": end-of-line
41 
42 # End /etc/inputrc
43 EOF

到此,我们的LFS的引导脚本和配置文件差不多就配置完了。一些设备配置文件和中文支持可以先略过。

下面开始编译安装内核以及GRUB引导程序。这一步完了之后,我们就可以启动LFS了。

首先创建 /etc/fstab 文件来确定LFS文件系统的挂载点,以什么样的顺序以及在挂载之前需要检查什么。

cat > /etc/fstab << "EOF"
# Begin /etc/fstab
    
# file system mount-point  type   options dump              fsck
#                                                            order

UUID="0983de48-2873-4c4a-9602-a2f2e5283f65"    /          ext4      defaults               1     1
UUID="2850a950-6dc8-41cf-bf5b-7501048234b3"    /boot    ext4    defaults          0    2
proc          /proc      proc      nosuid,noexec,nodev     0     0
sysfs         /sys       sysfs     nosuid,noexec,nodev     0     0
devpts        /dev/pts   devpts    gid=5,mode=620          0     0
tmpfs         /run       tmpfs     defaults                0     0
devtmpfs     /dev       devtmpfs  mode=0755,nosuid        0     0

# End /etc/fstab
EOF

接着开始编译安装内核:

cd /sources
tar xvf linux-3.10.10.tar.xz
cd linux-3.10.10
make mrproper

这能保证内核树绝对干净。内核开放团队推荐每次编译内核之前都运行这个命令。不要相信解压后的源码树就是干净的。

参考http://www.linuxfromscratch.org/hints/downloads/files/kernel-configuration.txt 来获得内核配置的常规信息。
用菜单形式界面的配置内核:(由于近期在 udev 中的改动,确保选择下面这些内容)

Device Drivers --->
    Generic Driver Options --->
        Maintain a devtmpfs filesystem to mount at /dev
make LANG=zh_CN.UTF-8 LC_ALL= menuconfig

确保把<host_LANG_value>替换为你的宿主系统下$LANG的值。如果宿主系统没有设置这个变量,就用宿主的$LC_ALL或者$LC_CTYPE的值代替。

在某些情况下选择 make oldconfig,可能会更适合。阅读 README

如果愿意,你可以直接从宿主系统中复制内核配置文件.config(如果可用),到linux-3.10.10的解压目录。当然,我们不推荐这个方式。通常探究所有配置菜单项,再根据需要创建内核是最佳的。
编译内核镜像和模块:

make

如果配置内核时使用了模块,那么就安装这些模块:

make modules_install

/boot

内核镜像的路径,根据不同的平台可能会改变,下面的文件名可根据你的喜好改变,但文件名的前缀必须是 vmlinuz 以便和下个部分中的提及的引导进程自动安装相兼容。下面的命令假定在x86架构上:

cp -v arch/x86/boot/bzImage /boot/vmlinuz-3.10.10-lfs-7.4

System.map

cp -v System.map /boot/System.map-3.10.10

由上面的 make menuconfig 步骤生成的内核配置文件 .config 包含所有刚刚被编译的内核配置选项。保存此文件以备日后查阅是一个好主意:

cp -v .config /boot/config-3.10.10

安装Linux内核文档:

install -d /usr/share/doc/linux-3.10.10
cp -r Documentation/* /usr/share/doc/linux-3.10.10

现在内核已经安装好了,如果这个内核源代码的目录准备保留,那么对linux-3.10.10 目录运行 chown -R 0:0命令 ,确保所有文件的属主是 root.

配置 Linux 模块的加载顺序:

大多时候,模块是自动被加载的,但有时候需要指定特定的顺序。加载模块的程序modprobe或insmod,使用/etc/modprobe.d/usb.conf了达到这个目的。
运行以下命令来创建一个新 /etc/modprobe.d/usb.conf 文件:

install -v -m755 -d /etc/modprobe.d
cat > /etc/modprobe.d/usb.conf << "EOF"
# Begin /etc/modprobe.d/usb.conf

install ohci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i ohci_hcd ; true
install uhci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i uhci_hcd ; true

# End /etc/modprobe.d/usb.conf
EOF

 

接下来,使用 GRUB 设置引导过程:
在这一部分,我打算把GRUB安装到我的移动硬盘的MBR中,这样的话,开机时选择从U盘启动,就可以启动LFS系统了。

首先了解下GRUB2命名驱动器的方式:
GRUB 使用自己的名称结构命名驱动器和分区,格式为 (hdn,m),其中 n 是硬盘驱动器编号,m 是分区编号。硬盘驱动器编号从 0 开始,但主分区的分区编号从 1 开始,扩展分区从 5 开始。注意这与早期版本中两个编号都从 0 开始是不同的。例如 sda1 分区对 GRUB 来说是 (hd0,1) 而 sdb3 就是 (hd1,3)。与Linux 不同,GRUB 不把 CD-ROM 驱动器认作硬盘驱动器。例如,如果在 hdb 上使用 CD,第二硬盘驱动器是 hdc,那么第二硬盘驱动器仍然会是 (hd1)。
关于grub2的更多信息,请参考https://wiki.archlinux.org/index.php/GRUB_(简体中文)GNU GRUB的维基百科也是不错的参考。

grub2的工作原理大致如下:
GRUB 通过向硬盘的第一物理磁道(估计就是MBR)写入数据(boot.img)来工作。这个区域不属于任何一个文件系统。其中的程序(boot.img,core.img)访问引导分区中的 GRUB 模块来进一步引导内核。grub模块的默认路径是 /boot/grub/。

我的移动硬盘的名称应该是/dev/sdb,引导分区是/dev/sdb1。(见LFS编译笔记1)
因此,安装 GRUB 文件到 /boot/grub 并建立引导磁道的命令是:

grub-install /dev/sdb

grub-install是我们在第二部分安装grub-2.00.tar.xz时的一个脚本,它会调用一系列命令来安装grub文件。

创建配置文件

cat > /boot/grub/grub.cfg << "EOF"
# Begin /boot/grub/grub.cfg
set default=0
set timeout=5

insmod ext2
set root=(hd1,1)  #这一步设置的是grub的根目录,grub会在这个目录中寻找内核的镜像文件。不过,由于设备名的随机性,此处通常都是错的。
            #目前,我还没有找到比较好的方法来固定这个名称,只能每次都在命令行下配置这一项。

menuentry "GNU/Linux, Linux 3.10.10-lfs-7.4" {
        linux /vmlinuz-3.10.10-lfs-7.4 root=/dev/sdb2 ro    #此处设置LFS系统的根目录。更好的选择是采用uuid而不是sdb这样的形式。
}
EOF

注意:
有一个命令 grub-mkconfig 能自动创建配置文件。它使用 /etc/grub.d/ 中的一系列脚本,并且会毁掉你的所有自定义配置。这些脚本是为不基于源代码的发行版设计的,不推荐用于LFS。如果你安装了商业 Linux 发行版,这个程序很可能会运行。记得备份你的 grub.cfg 文件。

到此,我们的LFS系统才真正编译完毕了。可以轻松一下了。重启时选择BIOS从U盘启动,就可以进入你的LFS系统的文本模式了。不过很有可能会卡在grub这一步,这是因为grub的配置文件设置的不正确,原因还是由于设备的命名是随机的,我们写在grub.cfg文件中的设备名称可能和真实的设备名称不同,这样就会导致grub不能正确的引导系统。不过,你不用慌,既然可以进入grub,就没有启动不起来的系统。不要小看了grub的命令行啊,它可是很强大的!
如果你真的卡在了grub这一关,那么就在grub的命令行下手工输入一下命令来启动LFS:

1 set root=(hd1,1)
2 linux /vmlinuz root=/dev/sdb2 ro
3 initrd /initrd.img
4 boot