说明
:
这里只对LFS的官方文档中没有详细阐述或有错误的操作步骤
,
命令等进行补充说明
,
所以
,
这不是一本LFS安装指南
,
只是自己在安装LFS过程中对LFS文档的一些补充
.
所以
,
请按照LFS的文档来安装LFS系统
,
如果发现某个安装步骤在本文档中有描述
,
请参照并以本文档为正确答案
=============================================================================================
1
.
LFS分区建立之前系统的分区情况
:
Disk
/
dev
/
hda
:
30.0
GB
,
30005821440
bytes
255
heads
,
63
sectors
/
track
,
3648
cylinders
Units
=
cylinders of
16065
*
512
=
8225280
bytes
Device Boot Start End Blocks Id
System
/
dev
/
hda1
*
1
765
6144831
7
HPFS
/
NTFS
/
dev
/
hda2
766
3204
19591267
+
f Win95 Ext
'
d (LBA)
/dev/hda3 3205 3334 1044225 82 Linux swap
/dev/hda5 766 2373 12916228+ 7 HPFS/NTFS
/dev/hda6 2374 3204 6674976 83 Linux
=============================================================================================
2. 创建分区
fdisk /dev/hda
键入m可以查看帮助, 键入p可以打印当前的分区表, 键入n可以新建一个分区, 键入w可以保存设置并退出, 键入q不保存设置退出
第一部分就是键入p之后打印出来的结果
键入n, 按照提示, 将未分配的2.4G的一个分区建立起来, 这里是/dev/hda4, 然后键入w
重启系统, 键入mke2fs /dev/hda4, 格式化分区
然后mount -t ext2 /dev/hda4 /mnt/lfs, 分区挂载完成
此时的分区表如下:
Disk /dev/hda: 30.0 GB, 30005821440 bytes
255 heads, 63 sectors/track, 3648 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 765 6144831 7 HPFS/NTFS
/dev/hda2 766 3204 19591267+ f Win95 Ext
'
d (LBA)
/
dev
/
hda3
3205
3334
1044225
82
Linux swap
/
dev
/
hda4
3335
3648
2522205
83
Linux
/
dev
/
hda5
766
2373
12916228
+
7
HPFS
/
NTFS
/
dev
/
hda6
2374
3204
6674976
83
Linux
=============================================================================================
3
.
动态加载器和标准连接器ld
动态加载器是用来寻找和加载共享库的
,
是Glibc的一部分; 标准连接器是binutils的一部分
,
用来将目标代码obj和共享库
,
静态库链接成可执行文件
所以
,
我的理解是
,
标准连接器是用来生成可执行文件的
,
而动态加载器是用来在执行可执行文件时
,
将该可执行文件用到的共享库加载到内存的
在LFS的中文官方文档中
,
把动态加载器也称为动态连接器
,
我个人十分不赞成这种说法
,
因为这使我把这个
"
动态连接器
"
和
"
标准连接器
"
混淆
称它为
"
动态加载器
"
更为确切
!
此外
,
在我的环境(RedHat9)下
,
通过命令 readelf
-
l
/
bin
/
rmdir
|
grep
interpreter 看到
,
我的动态加载器是
/
lib
/
ld
-
linux
.
so
.
2
=============================================================================================
4
.
关于gcc的编译细节问题
,
文档提到可以使用gcc
-
v来查看
,
这里写了一个helloworld
,
然后gcc
-
v的结果如下
:
Reading specs from
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/
specs
Configured with
:
../
configure
--
prefix
=/
usr
--
mandir
=/
usr
/
share
/
man
--
infodir
=/
usr
/
share
/
info
--
enable
-
shared
--
enable
-
threads
=
posix
--
disable
-
checking
--
with
-
system
-
zlib
--
enable
-
__cxa_atexit
--
host
=
i386
-
redhat
-
linux
Thread model
:
posix
gcc version
3.2
.
2
20030222
(Red Hat Linux
3.2
.
2
-
5
)
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/
cc1
-
lang
-
c
-
v
-
D__GNUC__
=
3
-
D__GNUC_MINOR__
=
2
-
D__GNUC_PATCHLEVEL__
=
2
-
D__GXX_ABI_VERSION
=
102
-
D__ELF__
-
Dunix
-
D__gnu_linux__
-
Dlinux
-
D__ELF__
-
D__unix__
-
D__gnu_linux__
-
D__linux__
-
D__unix
-
D__linux
-
Asystem
=
posix
-
D__NO_INLINE__
-
D__STDC_HOSTED__
=
1
-
Acpu
=
i386
-
Amachine
=
i386
-
Di386
-
D__i386
-
D__i386__
-
D__tune_i386__ hello
.
c
-
quiet
-
dumpbase hello
.
c
-
version
-
o
/
tmp
/
ccm7oBng
.
s
GNU CPP version
3.2
.
2
20030222
(Red Hat Linux
3.2
.
2
-
5
) (cpplib) (i386 Linux
/
ELF)
GNU C version
3.2
.
2
20030222
(Red Hat Linux
3.2
.
2
-
5
) (i386
-
redhat
-
linux)
compiled by GNU C version
3.2
.
2
20030222
(Red Hat Linux
3.2
.
2
-
5
)
.
ignoring nonexistent directory
"
/usr/i386-redhat-linux/include
"
#
include "..." search starts here:
#include <...> search starts here:
/
usr
/
local
/
include
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/
include
/
usr
/
include
End of search list
.
as
-
V
-
Qy
-
o
/
tmp
/
ccGGN20C
.
o
/
tmp
/
ccm7oBng
.
s
GNU assembler version
2.13
.
90.0
.
18
(i386
-
redhat
-
linux) using BFD version
2.13
.
90.0
.
18
20030206
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/
collect2
--
eh
-
frame
-
hdr
-
m elf_i386
-
dynamic
-
linker
/
lib
/
ld
-
linux
.
so
.
2
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/http://www.cnblogs.com/../
crt1
.
o
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/http://www.cnblogs.com/../
crti
.
o
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/
crtbegin
.
o
-
L
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
-
L
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/http://www.cnblogs.com/..
/
tmp
/
ccGGN20C
.
o
-
lgcc
-
lgcc_eh
-
lc
-
lgcc
-
lgcc_eh
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/
crtend
.
o
/
usr
/
lib
/
gcc
-
lib
/
i386
-
redhat
-
linux
/
3.2
.
2
/http://www.cnblogs.com/../
crtn
.
o
注意上面倒数第三行有一段
:
-
dynamic
-
linker
/
lib
/
ld
-
linux
.
so
.
2
,
这就是将来可执行文件中动态加载器的定义所在
,
这里也同时验证了LFS文档中的
一句话
:
"
对动态连接器的引用是作为硬路径嵌入每一个ELF共享程序中的,你可以用:'readelf -l <name of binary> | grep interpreter'来验证
"
=============================================================================================
5
.
"
在第二遍安装 Binutils时,我们可以利用--with-lib-path来控制ld的库搜索路径。从这里开始,核心工具链已经自给自足了。第五章的随后部份
都会连接到/tools下的新Glibc上,这样就对了
"
说这句话的原因是
,
在第一遍安装binutils和gcc的时候
,
所用的库都是原来系统的
,
而当LFS自身的GLIBC安装完成后
,
必须把binutils和gcc所使用到的库
都链接到这个新安装的GLIBC上
,
所以才需要安装第二遍binutils和gcc
另外
,
由于第一次
,
gcc binutils glibc都会安装在
$LFS
/
tools目录下
,
不符合UNIX系统的习惯
,
所以当chroot之后
,
就会重新安装glibc
,
将其放置到
/
usr
目录下(
/
usr
/
include
/
usr
/
lib)
,
此时
,
gcc和binutils就可以按照缺省设置来再重新安装了
,
不需要手动去改他们的安装配置了
!
也给今后安装其他
所有软件都扫平了道路
=============================================================================================
6
.
"
将库文件中的函数连接到使用它们的程序中,有两种方法:静态连接或动态连接。当一个程序是静态连接时,它使用的函数会包含在可执行文件中,结果就是比较大的执行文件。当一个程序是动态连接时,可执行文件中包含的是针对连接器的引用,说明了要使用的库文件名称,以及使用的函数名称,结果就是执行文件要小多了。这个可执行文件在某种程度上比静态连接的要慢,因为在运行时连接要花一些时间。(还有第三种方法,是使用动态连接器的可编程接口,参见dlopen的man文档,以获得更多信息。)
"
通过动态加载器的可编程接口
,
自己来装载动态库
!
=============================================================================================
7
.
"
su - lfs
"
"
-
"
让 su 命令启动一个新的,干净的shell
.
第一次听说
"
-
"
还有这个作用
=============================================================================================
8
.
摘录了LFS文档中比较精采的一段
,
特别是使用set
+
h这个开关关掉bash的hash功能
,
这一点很重要
,
有时候改动了环境变量make仍然失败
,
可能
原因就在这了
:
当你是lfs用户的身份时,用以下命令来设置一个好的工作环境:
cat
>
~/.
bash_profile
<<
"
EOF
"
set
+
h
umask
022
LFS
=/
mnt
/
lfs
LC_ALL
=
POSIX
PATH
=/
tools
/
bin
:
$PATH
export LFS LC_ALL PATH
unset CC CXX CPP LD_LIBRARY_PATH LD_PRELOAD
EOF
source
~/.
bash_profile
set
+
h 关掉bash的
"
hash
"
功能。hash 通常是一个有用的特性,这时 bash 使用 hash 表(哈希表)来记住可执行文件的完整路径,以避免为了找到同一个文件而进行多次 `PATH
'
搜索。然而,我们希望立刻就能使用新安装的工具。关掉hash功能,那些交互的命令(make,patch, sed,cp 等等)将总是使用新的程序。
把用户文件创建掩码(umask)设置为 022,保证新创建的文件和目录只能被文件的所有者执行写操作,而能被所有人读和执行。
LFS 变量自然要设置成你加载 LFS 分区的位置。
LC_ALL 变量控制某些软件包的本地化,使它们输出的信息遵守指定国家的规范。当你的主系统glibc版本低于2.2.4时,如果在第五章中把$LC_ALL设置成 "POSIX" 或 "C" 以外的值,当你退出第六章的chroot环境后,要再次进入就会有麻烦。设置成 "POSIX" (或"C",它们俩是相同的)我们保证在chroot环境中不会出现任何问题。
我们把 /tools/bin 附加到标准路径前面,是为了在安装过程中,总是能用到已经安装了的临时工具。
CC, CXX, CPP, LD_LIBRARY_PATH 和 LD_PRELOAD 环境变量都有可能破坏我们的第五章工具链,因此这里取消它们的设置,以预防可能的问题。
在用 source 命令读了刚才创建的设置文件后,我们已经准备好了,下面就开始编译下一章中要用到的临时工具。
=============================================================================================
9. 编译binutils-2.14的时间称为SBU时间, 在我的P10笔记本上耗时5分钟! 也就是说, 我的配置下, SBU时间是5分钟!
=============================================================================================
10. 在编译安装GLIBC的时候, 由于GCC3.3.1和GLIBC不兼容的缘故, 需要给GLIBC打个补丁才能正确编译, 这个补丁命令是:
patch -Np1 -i ../glibc-2.3.2-sscanf-1.patch
这里的patch命令, -N相当于--forward, 表示就算该补丁已经打过也照样再打, -p1参数的意思就是忽略掉后面补丁文件名路径中的第一个/
如果是p3, 那就忽略掉三个/ ; 最后参数-i表示指定补丁文件名(含路径), 这里也可以不用-i参数, 使用<这个重定向符号, 也可以表示把补丁文件
作为输入给patch, 如: patch -Np1 < ../glibc-2.3.2-sscanf-1.patch
=============================================================================================
11. 在做GLIBC的测试套件时, 发生一个超时错误, 如下(当时网线没插):
GCONV_PATH=/mnt/lfs/sources/glibc-build/iconvdata LC_ALL=C MALLOC_TRACE=/mnt/lfs/sources/glibc-build/resolv/tst-leaks.mtrace /mnt/lfs/sources/glibc-build/elf/ld-linux.so.2 --library-path /mnt/lfs/sources/glibc-build:/mnt/lfs/sources/glibc-build/math:/mnt/lfs/sources/glibc-build/elf:/mnt/lfs/sources/glibc-build/dlfcn:/mnt/lfs/sources/glibc-build/nss:/mnt/lfs/sources/glibc-build/nis:/mnt/lfs/sources/glibc-build/rt:/mnt/lfs/sources/glibc-build/resolv:/mnt/lfs/sources/glibc-build/crypt:/mnt/lfs/sources/glibc-build/linuxthreads /mnt/lfs/sources/glibc-build/resolv/tst-leaks > /mnt/lfs/sources/glibc-build/resolv/tst-leaks.out
Timed out: killed the child process but it exited 0
make[2]: *** [/mnt/lfs/sources/glibc-build/resolv/tst-leaks.out] Error 1
make[2]: Leaving directory `/mnt/lfs/sources/glibc-2.3.2/resolv
'
make[
1
]
:
***
[resolv
/
tests] Error
2
make[
1
]
:
Leaving directory `
/
mnt
/
lfs
/
sources
/
glibc
-
2.3
.
2
'
make: *** [check] Error 2
=============================================================================================
12. 在安装GLIBC的最后步骤, 如果运行了 make localedata/install-locales , 那么就不要运行下面的一堆命令了, 因为这个命令会install所有的locale信息.
=============================================================================================
13. LFS的文档上说, TCL的测试总是无法通过, 现实情况测试是, TCL的测试基本通过, 只有网络socket部分的测试没有通过, socket后续的测试没有完成,
就被我ctrl-c了 :)
=============================================================================================
14. LFS文档中在安装TCL完成后, 提醒TCL的源码目录不要删除, 这是因为后面的expert软件需要用到TCL源码目录下的一些头文件, 这里给出验证:
在安装expert的第一步configure的时候, 输出中有这样一句:
checking for Tcl private headers... found in /mnt/lfs/sources/tcl8.4.4/generic
这就证明LFS的文档所言非虚了, 但是这个configure是如何知道到/mnt/lfs/sources/tcl8.4.4/generic目录下去找的, 这就不知道了
=============================================================================================
15. 在第二遍安装binutils时, 最后的时候有这样的一句:
make -C ld LIB_PATH=/usr/lib:/lib
这里的LIB_PATH的设定是为将来的LFS系统服务的, 因为将来的LFS系统的库都在/usr/lib和/lib下, 所以这里要设定好, 然后在将来安装LFS系统的时候
重新安装binutils, 从而使动态加载器能到/usr/lib和/lib下去找库, 从而和/tools/lib等tools下的目录脱离关系
=============================================================================================
16. 给目录权限设置sticky位, 是为了保证属于该用户的文件只能被该用户删除.
通常用在一些对所有用户都开放权限的目录, 如/tmp, 由于这个目录所有的用户都有r w x的权限, 所以, 使用一个sticky, 可以保证一个文件不能被除
所有者之外的其他用户删除!
给目录或文件加sticky位, 在chmod时, 第一位设置成1即可, 如chmod 1777 /tmp
给一个文件设置sticky位, 已经不常用了, 原本的意思是告诉内核, 对于这种文件, 运行时尽量让其保留在内存中. 现在已经基本不用了
=============================================================================================
17. 在chroot之后, 安装GLIBC时, 做make check测试套件时, 没有出现错误! :)
=============================================================================================
18. 在LFS系统中安装coreutils时, 这句链接不知道是什么意思: ln -s test /bin/[
[ 这个恐怕是在shell中用来代替test的??
在RH9中查证, 发现还真有 [ 这个东东, 在/usr/bin目录下, 也是一个链接, 指向本目录下的test程序 :)
=============================================================================================
19. 在安装findutils时, 有这样一段描述, 却没有命令行, 不知应该怎么做才算正确:
"缺省情况下,updatedb 数据库的位置是 /usr/var.为了符合 FHS 规范,把它放在 /var/lib/misc/locatedb里,要把localstatedir=/var/lib/misc 参数传递给configure脚本. "
????
我看了configure脚本, 看到 "localstatedir=
'
${prefix}
/
var
'
", 说明的确是这样, 所以, 我在configure命令行里这样加上了参数:
./configure --prefix=/usr --libexecdir=/usr/bin --localstatedir=/var/lib/misc
=============================================================================================
20. 每次重新chroot, 进入LFS环境时, 需要注意以下两点,非常重要!!
1. 每次chroot之后, 需要重新mount两个文件系统-proc和devpts。有的时候会发现这两个文件系统已经挂上了,没有关系,因为一个文件本身就可以被多次挂载,更何况这两个是虚拟文件系统,如果不放心,可以将他们都一直umount直到出错,然后再mount上去即可,mount完了记得用df -ah查看一下
2. 做完chroot和mount proc,devpts时, 我觉得应该做一下set +h, 来去掉bash的hash功能,这可以通过这个命令做到:exec /tools/bin/bash --login + h ,也就是说,做完chroot和mount之后,请运行这个命令。如果已经在第六章中将新的bash安装好了,那么,请运行 exec /bin/bash --login +h =============================================================================================
21. 第六章里编译gcc时,有一处命令错误:
ln -s ../usr/bin/cpp /lib
其实就是在/lib下面创建一个cpp的链接,因为有些程序是硬到/lib下面去找cpp的。
这里../usr/bin/cpp不对,应该是/usr/bin/cpp,这个错误比较明显,危害不大,嘿嘿