最近想深入学习下Linux,以前对这个牛逼的东西了解不多,只是一些基本的、常用的操作。很久以前就知道有个LFS的东东,就是从头编译一个完整的Linux操作系统,于是就参照网上的教程,自己跟着学一学,顺便也加深对操作系统架构方面的了解。

参考文档 http://www.ha97.com/book/lfs-book-6.6/index.html

  (一)背景介绍

LFS,即Linux from Scratch,简单说就是从零开始,自己定制编译一个Linux操作系统。听起来很牛逼,做起来其实挺简单,基本工作就是从网上下载相关的软件包,在一个宿主系统上交叉编译,首先制作编译工具链,然后用工具链编译其他软件,最后配置各种脚本等,完成一个操作系统的构建。

具体参考http://lfs.linuxsir.org/main/

    http://www.linuxfromscratch.org/

    http://baike.baidu.com/view/366312.htm

  (二)基本概念

1、交叉编译:即在一个平台上生成另一个平台上的可执行代码,常用于嵌入式系统中。

2、宿主机(host):我们需要选择一台Linux主机作为宿主机,用来编译目标机的基础软件包。

3、目标机(target):运行编译出来的代码的机器,也就是我们定制的Linux系统。

4、平台描述:类似于x86_64-intel-Linux,描述了目标机的平台信息。

  (三)准备工作

1、需要下载的软件包及补丁

http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.8.tar.bz2
http://ftp.gnu.org/gnu/m4/m4-1.4.13.tar.bz2
http://ftp.gnu.org/gnu/make/make-3.81.tar.bz2
http://download.savannah.gnu.org/releases/man-db/man-db-2.5.6.tar.gz
http://www.kernel.org/pub/linux/docs/manpages/Archive/man-pages-3.23.tar.bz2
http://www.kernel.org/pub/linux/utils/kernel/module-init-tools/module-init-tools-3.11.1.tar.bz2
http://www.mpfr.org/mpfr-2.4.2/mpfr-2.4.2.tar.bz2
ftp://ftp.gnu.org/gnu/ncurses/ncurses-5.7.tar.gz
http://ftp.gnu.org/gnu/patch/patch-2.6.1.tar.bz2
http://cpan.org/src/5.0/perl-5.10.1.tar.bz2
http://pkgconfig.freedesktop.org/releases/pkg-config-0.23.tar.gz
http://procps.sourceforge.net/procps-3.2.8.tar.gz
http://prdownloads.sourceforge.net/psmisc/psmisc-22.10.tar.gz
http://ftp.gnu.org/gnu/readline/readline-6.1.tar.gz
http://ftp.gnu.org/gnu/sed/sed-4.2.1.tar.bz2
ftp://pkg-shadow.alioth.debian.org/pub/pkg-shadow/shadow-4.1.4.2.tar.bz2
http://www.infodrom.org/projects/sysklogd/download/sysklogd-1.5.tar.gz
ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.86.tar.gz
http://ftp.gnu.org/gnu/tar/tar-1.22.tar.bz2
http://prdownloads.sourceforge.net/tcl/tcl8.5.8-src.tar.gz
http://ftp.gnu.org/gnu/texinfo/texinfo-4.13a.tar.gz
http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-151.tar.bz2
http://www.linuxfromscratch.org/lfs/downloads/6.6/udev-config-20100128.tar.bz2
http://www.kernel.org/pub/linux/utils/util-linux-ng/v2.17/util-linux-ng-2.17.tar.bz2
ftp://ftp.vim.org/pub/vim/unix/vim-7.2.tar.bz2
ftp://ftp.vim.org/pub/vim/extra/vim-7.2-lang.tar.gz
http://www.zlib.net/zlib-1.2.3.tar.bz2
http://www.linuxfromscratch.org/patches/lfs/6.6/bzip2-1.0.5-install_docs-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/coreutils-8.4-i18n-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/coreutils-8.4-uname-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/diffutils-2.8.1-i18n-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/expect-5.43.0-spawn-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/expect-5.43.0-tcl_8.5.5_fix-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/flex-2.5.35-gcc44-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/gcc-4.4.3-startfiles_fix-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/gettext-0.17-upstream_fixes-2.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/grep-2.5.4-debian_fixes-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/kbd-1.15.1-backspace-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/make-3.81-upstream_fixes-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/patch-2.6.1-test_fix-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/perl-5.10.1-libc-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/perl-5.10.1-utf8-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/procps-3.2.8-watch_unicode-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.6/vim-7.2-fixes-5.patch

部分软件包按照上面的url不能下载,可以到google上搜索下载。

2、准备文件系统

(1)在宿主Linux上划出一块空闲分区,我是在虚拟机上做实验,就直接增加一块10G硬盘,在系统中显示为/dev/sdb,使用fdisk工具将硬盘分成8G的数据区和2G的swap分区,分别是/dev/sdb1和/dev/sdb2。

(2)对分区分别进行格式化

mkfs.ext3 /dev/sdb1

mkswap /dev/sdb2

(3)将/dev/sdb1挂载到/mnt/lfs目录下

export LFS=/mnt/lfs

mkdir $LFS

mount -t ext3 /dev/sdb1 $LFS

/sbin/swapon -v /dev/sdb2

(4)创建源码包目录和工具链目录

sources目录用于存放下载的软件包源代码,构建工具链时,单独编译每个软件包最好新建一个build目录进行编译,然后设置prefix安装到/tools目录下,安装完成后需要将源代码目录和build目录删除,以免多次编译时相互影响。

mkdir $LFS/sources

chmod a+wt $LFS/sources

mkdir $LFS/tools    tools目录用于存放目标机的编译工具链,以便于区分宿主机的环境

ln -s $LFS/tools /    在宿主机上创建tools目录的符号连接

(5)创建专门的lfs用户

在编译过程中,为了避免宿主系统环境的影响,最好是另外建立一个lfs用户,以保证编译环境的干净。

groupadd lfs

useradd -s /bin/bash -g lfs -m -k /dev/null lfs

passwd lfs

chown -v lfs:lfs $LFS

chown -v lfs $LFS/tools

chown -v lfs $LFS/sources

(6)设置lfs用户的环境变量

在这里有.bash_profile和.bashrc两个文件,.bash_profile为登录shell设置环境变量,.bashrc为非登录shell设置环境变量。

在lfs的.bash_profile中写入以下内容:

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

在.bashrc中写入以下内容:

set +h

umask 22

LFS=/mnt/lfs

LC_ALL=POSIX

LFS_TGT=$(uname -m)-lfs-linux-gnu   设置平台描述,用在交叉编译时

PATH=/tools/bin:/bin:/usr/bin

export LFS LC_ALL LFS_TGT PATH

  (四)编译工具链

 工具链是一组独立于宿主系统的工具集,用来编译目标机上的其他软件,主要包括gcc,binutils,glibc等几个包。

1、binutils

binutils是一组二进制工具集,包括addr2line ar gprof nm objcopy objdump ranlib size strings strip等(包含连接器,汇编器,反汇编器等),可用于对编译好的二进制文件进行处理。gcc必须和binutils一起才能正常运行。

Binutils 将汇编器和连接器安装在两个位置: /tools/bin 和 /tools/$LFS_TGT/bin,连接器主要用于库文件的搜索路径,ld --verbose | grep SEARCH可以显示当前搜索路径和顺序。gcc必须跟连接器一起使用,可以用命令gcc -print-prog-name=ld查看gcc使用哪个标准连接器。

创建单独的编译目录:

mkdir -v ../binutils-build

cd ../binutils-build

配置binutils:

../binutils-2.20/configure \
   --target=$LFS_TGT --prefix=/tools \
   --disable-nls --disable-werror

如果是X86_64平台,需要执行mkdir -v /tools/lib && ln -sv lib /tools/lib64

make

make install

2、GCC

GCC是Linux下的标准编译器,但是需要跟Binutils 提供的二进制工具一起使用。

解压缩依赖的gmp和mpfr:

 tar -jxf ../mpfr-2.4.2.tar.bz2

mv mpfr-2.4.2 mpfr

tar -jxf ../gmp-5.0.0.tar.bz2  

mv gmp-5.0.0 gmp

创建单独的编译目录:

mkdir ../gcc-build

cd ../gcc-build

配置GCC:

../gcc-4.4.3/configure \
   --target=$LFS_TGT --prefix=/tools \
   --disable-nls --disable-shared --disable-multilib \
   --disable-decimal-float --disable-threads \
   --disable-libmudflap --disable-libssp \
   --disable-libgomp --enable-languages=c

 make

make install

建立Glibc对libgcc_eh.a的依赖:

ln -vs libgcc.a `$LFS_TGT-gcc -print-libgcc-file-name |  sed 's/libgcc/&_eh/'

3、Glibc

Glibc是GUN的标准C库,编译应用程序可能会依赖于这些C库。

从Linux内核中提取Header,为Glibc使用:

make mrproper

make headers_check

make INSTALL_HDR_PATH=dest headers_install

cp -rv dest/include/* /tools/include

创建单独的编译目录:

mkdir -v ../glibc-build

cd ../glibc-build

配置Glibc:

../glibc-2.11.1/configure --prefix=/tools \
   --host=$LFS_TGT --build=$(../glibc-2.11.1/scripts/config.guess) \
   --disable-profile --enable-add-ons \
   --enable-kernel=2.6.18 --with-headers=/tools/include \
   libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes

make 

make install

4、按照步骤,重新编译binutils和gcc。

然后依次安装

Tcl-8.5.8

Expect-5.43.0

DejaGNU-1.4.4

Ncurses-5.7

Bash-4.1

Bzip2-1.0.5

Coreutils-8.4

Diffutils-2.8.1

Findutils-4.4.2

Gawk-3.1.7

Gettext-0.17

Grep-2.5.4

Gzip-1.4

M4-1.4.13

Make-3.81

Patch-2.6.1

Perl-5.10.1

Sed-4.2.1

Tar-1.22

Texinfo-4.13a

安装完成后,就完成了一个包含基本工具链的操作系统。