歡迎您光臨本站 註冊首頁

一個自編內核的LINUX

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

前提:(課堂實驗)

1、一個作為宿主機的Linux;本文使用的是Redhat Enterprise Linux 5.4;

2、在宿主機上提供一塊額外的硬碟作為新系統的存儲盤,為了降低複雜度,這裡添加使用一塊IDE介面的新硬碟;

3、Linux內核源碼,busybox源碼;本文使用的是目前最新版的linux-2.6.34.1和busybox-1.16.1.

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

一、為系統上的新硬碟建立分區,這裡根據需要先建立一個大小為100M的主分區作為新建系統的boot分區和一個512M的分區作為目標系統(即正在構建的新系統,後面將沿用此名稱)的根分區;100M的分區格式化后將其掛載至/mnt/boot目錄下;512M的分區格式化后將掛載至/mnt/sysroot目錄;

說明:

1、此處的boot和sysroot的掛載點目錄名稱盡量不要修改,尤其是boot目錄,否則您必須保證後面的許多步驟都做了相應的改動;

2、新建系統的boot目錄也可以跟根目錄在同一個分區,這種方式比獨立分區還要簡單些,因此這裡將不對此種方法再做出說明;

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

# cd /usr/src

# tar jxvf linux-2.6.34.1.tar.bz2

# ln -sv linux-2.6.34.1 linux

# cd linux

# make menuconfig

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

# make SUBDIR=arch/

# cp arch/x86/boot/bzImage /mnt/boot

# make menuconfig

三、編譯busybox

# cd /usr/src

# tar -jxvf busybox-1.16.1.tar.bz2

# cd busybox-1.16.1

# make menuconfig

說明:

1、此處需要選擇 Busybox Settings --> Build Options --> Build BusyBox as a static binary (no shared libs),這樣可以把Busybox編譯成一個不使用共享庫的靜態二進位文件,從而避免了對宿主機的共享庫產生依賴;但你也可以不選擇此項,而完成編譯后把其依賴的共享庫複製至目標系統上的/lib目錄中即可;這裡採用后一種辦法.

2、修改安裝位置為/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

四、製作initrd

# cd /mnt/temp

1、建立rootfs:

# mkdir -pv proc sys etc/init.d tmp dev mnt/sysroot

2、創建兩個必要的設備文件:

# mknod dev/console c 5 1

# mknod dev/null c 1 3

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

4、製作initrd

# find . | cpio --quiet -H newc -o | gzip -9 -n > /mnt/boot/initrd.gz

五、建立真正的根文件系統

# cd /mnt/sysroot

1、建立rootfs:

# mkdir -pv proc sys etc/init.d tmp dev boot var/log lib

2、創建兩個必要的設備文件:

# mknod dev/console c 5 1

# mknod dev/null c 1 3

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

4、配置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

5、為系統準備一個「文件系統表」配置文件/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

6、由於在rcS文件中啟動了日誌進程,因此系統在運行中會產生大量日誌並將其顯示於控制台;這將會經常性的打斷正在進行的工作,為了避免這種情況,我們這裡為日誌進程建立配置文件,為其指定將日誌發送至/var/log/messages文件;

# vim etc/syslog.conf

添加如下一行:

*.info /var/log/messages

六、好了,至此一個簡易的基於內存運行的小系統已經構建出來了,我們接下來為此系統創建所需的引導程序

# 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

接下來將此塊硬碟接入一個新的主機(這裡使用的是虛擬機),啟動一下並測試使用.

七、為新構建的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

好了,接下來就可以測試驗正六個虛擬控制台的使用了.

八、儘管上述第七步已經實現了虛擬控制台,但其仍是直接進入系統,且系統沒有用戶帳號等安全設施,這將不利於系統的安全性.因此,接下來的這步實現為系統添加用戶帳號(這裡仍然基於宿主機實現).

1、為目標主機建立passwd帳號文件

# cd /mnt/sysroot

# vim etc/passwd

添加如下內容:

root:x:0:0::/root:/bin/sh

接下來為root用戶建立「家」目錄:

# mkdir root

2、為目標主機建立group帳號文件

# vim etc/group

添加如下內容:

root:x:0:

3、為目標主機建立shadow影子口令文件,這裡採用直接複製宿主機的shadow文件中關於root口令行的行來實現

# grep "^root" /etc/shadow > etc/shadow

註:等目標主機啟動時,root用戶的口令也是宿主機的root用戶的口令.

4、將 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

好了,接下來就可以重新啟動目標主機進行驗正了.

九、在系統登錄時提供banner信息

這個可以通過宿主機來實現,也可以直接在目標主機上進行配置.這裡採用直接在目標主機上配置的方式:

# vi /etc/issue

添加如下內容:

Welcome to ToyLinux(http://marion.cublog.cn)...

Kernel \r

註:這裡的內容可以根據你的需要進行修改.

十、在系統啟動時為系統提供主機名稱:

這個可以通過宿主機來實現,也可以直接在目標主機上進行配置.這裡採用直接在目標主機上配置的方式:

1、創建保存主機名稱的配置文件

# mkdir /etc/sysconfig

# vi /etc/sysconfig/network

添加如下內容:

HOSTNAME=marion.example.com

2、編輯系統初始化腳本,實現開機過程中設定主機名稱

# 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

十一、移植宿主機的bash至目標主機,以實現在目標主機上使用bash

1、在宿主機上查看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)

2、此時,我們需要把除了第一行顯示的以外的餘下的所有庫文件複製到目標主機的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/

3、而後再把bash程序複製到目標主機的bin目錄中即可:

# cp /bin/bash bin/

十二、設置root用戶的默認shell為/bin/bash,並為其定義常用環境變數(本過程在目標主機上直接實現)

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

# vi /etc/shells

添加如下內容:

/bin/sh

/bin/bash

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

3、編輯/root/.bash_profile,定義PATH, PS1等環境變數

# vim /root/.bash_profile

添加如下內容:

PS1='[\u@\h \W]\$'

HISTSIZE=100

PATH=$PATH:/$HOME/bin

export PS1 HISTSIZE PATH

十三、定義名稱解析方式

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

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

1、為名稱解析服務複製必要的庫文件:

# cd /mnt/sysroot

# cp /lib/libnss_files* lib/

# cp /lib/libnss_dns* lib/

2、為目標主機建立名稱解析文件nsswitch.conf

# vim etc/nsswitch.conf

添加如下內容:

passwd: files

group: files

shadow: files

hosts: files dns

3、為主機名稱解析建立etc/hosts文件,可根據需要添加其內容

# vim etc/hosts

添加如下內容(如果本機有IP地址,也可以在此配置):

127.0.0.1 localhost

十四、為目標主機提供一個web伺服器

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

1、在宿主機上編譯thttpd

# tar zxvf thttpd-2.25b.tar.gz

# cd thttpd-2.25b

# ./configure

# make

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

# mkdir -pv /mnt/sysroot/usr/local/sbin

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

3、複製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目錄中.

4、為目標主機上運行thttpd進程建立一個有效用戶帳號(此用戶不需要「家」目錄)

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

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

5、接下來啟動目標主機系統,登錄后創建網站目錄,並創建一個測試頁面

# mkdir /var/www/html

# echo '<h1>A test page.</h1>' &gt; /var/www/html/index.html

而後啟動thttpd進程:

# /usr/local/sbin/thttpd -u www -dd /var/www/html -l /var/log/thttpd.log &

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


[火星人 ] 一個自編內核的LINUX已經有729次圍觀

http://coctec.com/docs/linux/show-post-50400.html