zoukankan      html  css  js  c++  java
  • LFS安装手记

    说明:
    这里只对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 -/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---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.-quiet -dumpbase hello.-version -/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 
    --Qy -/tmp/ccGGN20C./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./usr/lib/gcc-lib/i386-redhat-linux/3.2.2/http://www.cnblogs.com/../crti./usr/lib/gcc-lib/i386-redhat-linux/3.2.2/crtbegin.-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.-lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/lib/gcc-lib/i386-redhat-linux/3.2.2/crtend./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,这个错误比较明显,危害不大,嘿嘿
  • 相关阅读:
    《编程珠玑番外篇-O 中间语言和虚拟机漫谈》
    《编译原理之美》笔记——后端部分
    《编译原理之美》笔记——前端部分
    《从语言编译器源码入手,编译原理该这么学》
    知识图谱简介
    支持向量机原理讲解(一)
    一个完整的机器学习项目在Python中演练(四)
    多GPU使用详解
    数据可视化
    详解谱聚类原理
  • 原文地址:https://www.cnblogs.com/super119/p/1910245.html
Copyright © 2011-2022 走看看