內核編譯基礎篇(一)


前提:(kernel和buzybox、thttpd請到官方下載,.config文件見附件)
一、一個做爲宿主機的Linux;本文使用的是Redhat Enterprise Linux 5.4;
二、在宿主機上提供一塊額外的硬盤做爲新系統的存儲盤,爲了下降複雜度,這裏添加使用一塊IDE接口的新硬盤;
三、Linux內核源碼,busybox源碼;本文使用的是目前最新版的linux-2.6.34.1和busybox-1.16.1。html

說明:本文是一個step by step的實作指南;linux

1、爲系統上的新硬盤創建分區,這裏根據須要先創建一個大小爲100M的主分區做爲新建系統的boot分區和一個512M的分區做爲目標系統(即正在構建的新系統,後面將沿用此名稱)的根分區;100M的分區格式化後將其掛載至/mnt/boot目錄下;512M的分區格式化後將掛載至/mnt/sysroot目錄;web

說明:
一、此處的boot和sysroot的掛載點目錄名稱儘可能不要修改,尤爲是boot目錄,不然您必須保證後面的許多步驟都作了相應的改動;
二、新建系統的boot目錄也能夠跟根目錄在同一個分區,這種方式比獨立分區還要簡單些,所以這裏將不對此種方法再作出說明;shell

2、編譯內核源代碼,爲新系統提供一個所需的內核(本例中的源代碼包都位於/usr/src目錄中)vim

# cd  /usr/src
# tar jxvf linux-2.6.34.1.tar.bz2
# ln  -sv  linux-2.6.34.1  linux
# cd linux安全

# make menuconfigbash

根據您的實際和規劃選擇所須要的功能;本實例計劃製做一個具備網絡的功能的tiny linux且不打算使用內核模塊,所以,這裏選擇把本機對應的網卡驅動直接編譯進了內核。做者使用的是vmware Workstation虛擬機,因此,所需的網上驅動是pcnet32的,其它的均按須要選擇。選擇完成後須要保存至當前目錄下.config文件中。服務器

# make  SUBDIR=arch/
# cp arch/x86/boot/bzImage  /mnt/boot網絡

# make menuconfigide

====================================================================

3、編譯busybox

# cd /usr/src
# tar  -jxvf  busybox-1.16.1.tar.bz2
# cd  busybox-1.16.1

# make menuconfig

說明:
一、此處須要選擇 Busybox Settings --> Build Options -->  Build BusyBox as a static binary (no shared libs),這樣能夠把Busybox編譯成一個不使用共享庫的靜態二進制文件,從而避免了對宿主機的共享庫產生依賴;但你也能夠不選擇此項,而完成編譯後把其依賴的共享庫複製至目標系統上的/lib目錄中便可;這裏採用後一種辦法。
二、修改安裝位置爲/mnt/root;方法爲:Busybox Settings --> Installation Options --> (./_install) BusyBox installation prefix,修改其值爲/mnt/sysroot。

# make  install

安裝後的文件均位於/mnt/sysroot目錄中;但爲了建立initrd,並實現讓其啓動之後將真正的文件系統切換至目標系統分區上的rootfs,您還須要複製一份剛安裝在/mnt/sysroot下的busybox至另外一個目錄,以實現與真正的根文件系統分開製做。咱們這裏選擇使用/mnt/temp目錄;

# mkdir -pv /mnt/temp
# cp -r /mnt/sysroot/*  /mnt/temp

====================================================================

4、製做initrd

# cd  /mnt/temp

一、創建rootfs:
# mkdir -pv  proc  sys  etc/init.d  tmp  dev  mnt/sysroot

二、建立兩個必要的設備文件:
# mknod  dev/console  c  5  1
# mknod  dev/null  c  1  3

三、爲initrd製做init程序,此程序的主要任務是實現rootfs的切換,所以,能夠以腳本的方式來實現它:

# rm  linuxrc
# vim  init
添加以下內容:
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mdev -s
mount -t ext3 /dev/hda2  /mnt/sysroot
exec  switch_root  /mnt/sysroot  /init

給此腳本執行權限:
chmod  +x  init

四、製做initrd
# find  .  | cpio  --quiet  -H newc  -o  | gzip  -9 -n > /mnt/boot/initrd.gz
=========================================================================================
5、創建真正的根文件系統

# cd  /mnt/sysroot

一、創建rootfs:
# mkdir -pv  proc  sys  etc/init.d  tmp  dev  boot  var/log lib

二、建立兩個必要的設備文件:
# mknod  dev/console  c  5  1
# mknod  dev/null  c  1  3

三、創建系統初始化腳本文件

# vim  etc/init.d/rcS

添加以下內容:
 
#!/bin/sh
echo -e "            Welcome to  \033[31mToyLinux\033[0m\n                "

echo -e "Mounting the filesystem .................[  \033[32mOK\033[0m  ]"
mount -t proc proc /proc
mount -t sysfs  sysfs  /sys

echo -e "Creating the files of device ............[  \033[32mOK\033[0m  ]"
mdev -s

echo -e "Mounting the filesystem .................[  \033[32mOK\033[0m  ]"
mount -a

echo -e "Remounting the root filesystem ..........[  \033[32mOK\033[0m  ]"
mount  -o  remount,rw  /

echo -e "Starting the log daemon .................[  \033[32mOK\033[0m  ]"
syslogd
klogd

echo -e "Configuring loopback interface ..........[  \033[32mOK\033[0m  ]"
ifconfig  lo  127.0.0.1/24

# END

然後讓此腳本具備執行權限:
chmod +x  etc/init.d/rcS
四、配置init及其所須要inittab文件

# cd  /mnt/sysroot
# mv  linuxrc  init

# vim  etc/inittab

添加以下內容:

::sysinit:/etc/init.d/rcS
console::respawn:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

五、爲系統準備一個「文件系統表」配置文件/etc/fstab
# vim  etc/fstab

添加以下內容:
/dev/hda2               /                       ext3    defaults        1 1
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
/dev/hda1               /boot                   ext3    defaults        0 0

六、因爲在rcS文件中啓動了日誌進程,所以系統在運行中會產生大量日誌並將其顯示於控制檯;這將會常常性的打斷正在進行的工做,爲了不這種狀況,咱們這裏爲日誌進程創建配置文件,爲其指定將日誌發送至/var/log/messages文件;

# vim  etc/syslog.conf

添加以下一行:
*.info    /var/log/messages

====================================================================

6、好了,至此一個簡易的基於內存運行的小系統已經構建出來了,咱們接下來爲此係統建立所需的引導程序

# grub-install  --root-directory=/mnt  /dev/hda

說明:此處的/dev/hda爲目標系統所在的那塊新磁盤;

接下來爲grub創建配置文件:
# vim  /mnt/boot/grub/grub.conf

添加相似以下內容:

default  0
timeout  3
color light-green/black light-magenta/black
title ToyLinux (2.6.34.1)
 root (hd0,0)
 kernel /bzImage ro root=/dev/hda2 quiet
 initrd /initrd.gz


接下來將此塊硬盤接入一個新的主機(這裏使用的是虛擬機),啓動一下並測試使用。

===============================================================================

7、爲新構建的ToyLinux啓用虛擬控制檯

這個能夠經過宿主機來實現,也能夠直接啓動剛構建成功的小Linux進行配置。咱們這裏採用經過宿主機的方式(從新啓動宿主機):
# cd /mnt/sysroot

將 etc/inittab文件改成以下內容:
::sysinit:/etc/init.d/rcS
tty1::askfirst:/bin/sh
tty2::askfirst:/bin/sh
tty3::askfirst:/bin/sh
tty4::askfirst:/bin/sh
tty5::askfirst:/bin/sh
tty6::askfirst:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

好了,接下來就能夠測試驗正六個虛擬控制檯的使用了。
==================================================================================
8、儘管上述第七步已經實現了虛擬控制檯,但其還是直接進入系統,且系統沒有用戶賬號等安全設施,這將不利於系統的安全性。所以,接下來的這步實現爲系統添加用戶賬號(這裏仍然基於宿主機實現)。

一、爲目標主機創建passwd賬號文件
# cd /mnt/sysroot
# vim etc/passwd

添加以下內容:
root:x:0:0::/root:/bin/sh

接下來爲root用戶創建「家」目錄:
# mkdir  root

二、爲目標主機創建group賬號文件
# vim  etc/group

添加以下內容:
root:x:0:

三、爲目標主機創建shadow影子口令文件,這裏採用直接複製宿主機的shadow文件中關於root口令行的行來實現
# grep  "^root"  /etc/shadow  > etc/shadow

注:等目標主機啓動時,root用戶的口令也是宿主機的root用戶的口令。

四、將 etc/inittab文件改成以下內容:
::sysinit:/etc/init.d/rcS
::respawn:/sbin/getty 38400 tty1
::respawn:/sbin/getty 38400 tty2
::respawn:/sbin/getty 38400 tty3
::respawn:/sbin/getty 38400 tty4
::respawn:/sbin/getty 38400 tty5
::respawn:/sbin/getty 38400 tty6
::shutdown:/bin/umount -a -r
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r


好了,接下來就能夠從新啓動目標主機進行驗正了。
========================================================================
9、在系統登陸時提供banner信息

這個能夠經過宿主機來實現,也能夠直接在目標主機上進行配置。這裏採用直接在目標主機上配置的方式:

# vi  /etc/issue
添加以下內容:
Welcome to ToyLinux(http://marion.cublog.cn)...
Kernel \r


注:這裏的內容能夠根據你的須要進行修改。
==================================================================
10、在系統啓動時爲系統提供主機名稱:

這個能夠經過宿主機來實現,也能夠直接在目標主機上進行配置。這裏採用直接在目標主機上配置的方式:

一、建立保存主機名稱的配置文件
# mkdir /etc/sysconfig
# vi  /etc/sysconfig/network
添加以下內容:
HOSTNAME=marion.example.com

二、編輯系統初始化腳本,實現開機過程當中設定主機名稱
# vi /etc/init.d/rcS
在文件尾部添加以下行:

HOSTNAME=
[ -r /etc/sysconfig/network ] && source /etc/sysconfig/network
[ -z ${HOSTNAME} ] && HOSTNAME="localhost"
[-x /bin/hostname ] && /bin/hostname  ${HOSTNAME}
unset HOSTNAME

11、移植宿主機的bash至目標主機,以實如今目標主機上使用bash

一、在宿主機上查看bash所依賴的庫文件件,並將這些庫文件複製到目標系統:

# cd  /mnt/sysroot
# ldd /bin/bash  (其顯示可能相似以下所示:)
 linux-gate.so.1 =>  (0x003c0000)
 libtermcap.so.2 => /lib/libtermcap.so.2 (0x00aa6000)
 libdl.so.2 => /lib/libdl.so.2 (0x00604000)
 libc.so.6 => /lib/libc.so.6 (0x008c8000)
 /lib/ld-linux.so.2 (0x00bf8000)

二、此時,咱們須要把除了第一行顯示的之外的餘下的全部庫文件複製到目標主機的lib目錄中:
# cp  /lib/libtermcap.so.2  lib/
# cp  /lib/libdl.so.2  lib/
# cp  /lib/libc.so.6  lib/
# cp  /lib/ld-linux.so.2  lib/

三、然後再把bash程序複製到目標主機的bin目錄中便可:
# cp /bin/bash  bin/
======================================================================
12、設置root用戶的默認shell爲/bin/bash,併爲其定義經常使用環境變量(本過程在目標主機上直接實現)

一、新建/etc/shells文件,標明當前系統所用可用shell類型:
# vi /etc/shells

添加以下內容:
/bin/sh
/bin/bash

二、編輯/etc/passwd,設置root用戶的默認shell爲/bin/bash

三、編輯/root/.bash_profile,定義PATH, PS1等環境變量
# vim  /root/.bash_profile

添加以下內容:
PS1='[\u@\h \W]\$'
HISTSIZE=100
PATH=$PATH:/$HOME/bin

export PS1 HISTSIZE PATH
===========================================
十3、定義名稱解析方式

完成上述第十二步之後,用戶的shell提示符中的用戶名極可能顯示爲:」I have no name!「,這個主要是沒有配置名稱解析服務形成的。本步驟則來嘗試解決此問題,並嘗試實現爲主機名稱解析定義其解析方式。

提示:本步驟須要在宿主機上實現

一、爲名稱解析服務複製必要的庫文件:
# cd /mnt/sysroot
# cp /lib/libnss_files*  lib/
# cp /lib/libnss_dns*  lib/

二、爲目標主機創建名稱解析文件nsswitch.conf
# vim etc/nsswitch.conf

添加以下內容:
passwd:  files
group:  files
shadow:  files

hosts:  files dns

三、爲主機名稱解析創建etc/hosts文件,可根據須要添加其內容
# vim  etc/hosts

添加以下內容(若是本機有IP地址,也能夠在此配置):
127.0.0.1  localhost

十4、爲目標主機提供一個web服務器

嵌入式系統上可用的輕量級web服務器有如Boa, thttpd, lighttpd, shttpd等。咱們這裏選用thttpd,且只提供簡單的web服務。

一、在宿主機上編譯thttpd

# tar zxvf thttpd-2.25b.tar.gz
# cd  thttpd-2.25b

# ./configure
# make

二、複製編譯好的thttpd至目標主機

# mkdir -pv /mnt/sysroot/usr/local/sbin
# cp -p thttpd  /mnt/sysroot/usr/local/sbin/

三、複製thttpd依賴的庫文件至目標主機
# ldd thttpd
 linux-gate.so.1 =>  (0x00e75000)
 libcrypt.so.1 => /lib/libcrypt.so.1 (0x04f3a000)
 libc.so.6 => /lib/libc.so.6 (0x00931000)
 /lib/ld-linux.so.2 (0x0090e000)

請確保以上所依賴的庫文件均複製到了/mnt/sysroot/lib目錄中。

四、爲目標主機上運行thttpd進程創建一個有效用戶賬號(此用戶不須要「家」目錄)

# echo "www:x:1000:1000:www::/bin/bash" >> /mnt/sysroot/passwd
# echo "www:x:1000:" >> /mnt/sysroot/group

五、接下來啓動目標主機系統,登陸後建立網站目錄,並建立一個測試頁面
# mkdir /var/www/html
# echo '<h1>A test page.</h1>' > /var/www/html/index.html

然後啓動thttpd進程:
# /usr/local/sbin/thttpd  -u www -dd /var/www/html -l /var/log/thttpd.log &

接下來就能夠進行測試訪問了。請確保此時目標主機有合適的IP地址。

相關文章
相關標籤/搜索