一步步手動構建小于10M的類嵌入式Linux系統

2016年11月5日11:11:38 1 4,647 ℃

前提:

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

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

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

說明:本文是一個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.38.5.tar.bz2

# ln  -sv  linux-2.6.38.5  linux

# cd linux

然后下載ftp://172.16.0.1/pub/Sources/kernel/kernel-2.6.38.1-i686.cfg至當前目錄中,并重命名為.config。

# make menuconfig

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

# make  SUBDIR=arch/

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

# make menuconfig

提示:為了實現后面的功能,請務必將文件系統中的ext3和網卡的驅動程序直接編譯進內核;否則,就需要手動裝載這些相關文件系統的模塊;

三、編譯busybox

# cd /usr/src

# tar  -jxvf  busybox-1.20.2.tar.bz2

# cd  busybox-1.20.2

# mkdir include/mtd 

# cp  /usr/src/linux/include/mtd/ubi-user.h  include/mtd/

# make menuconfig

說明:

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

2、修改安裝位置為/mnt/sysroot;方法為:Busybox Settings --> Installation Options --> (./_install) BusyBox installation prefix,修改其值為/mnt/sysroot。

# make  install

安裝后的文件均位于/mnt/sysroot目錄中;但為了創建initrd,并實現讓其啟動以后將真正的文件系統切換至目標系統分區上的rootfs,您還需要復制一份剛安裝在/mnt/sysroot下的busybox至另一個目錄,以實現與真正的根文件系統分開制作。我們這里選擇使用/mnt/temp目錄;

# mkdir -pv /tmp/busybox

# cp -r /mnt/sysroot/*  /tmp/busybox

四、制作initrd

# cd  /tmp/busybox

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

insmod /lib/modules/jbd.ko

insmod /lib/modules/ext3.ko

mdev -s

mount -t ext3 /dev/hda2  /mnt/sysroot

exec  switch_root  /mnt/sysroot  /sbin/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/rc.d/init.d  tmp  dev/pts  boot  var/log  usr/lib

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

# mknod  dev/console  c  5  1

# mknod  dev/null  c  1  3

3、建立系統初始化腳本文件

# vim  etc/rc.d/rc.sysinit

添加如下內容:

  

#!/bin/sh

echo -e "\tWelcome to  \033[31mMageEdu\033[0m Linux"

echo -e "Remounting the root filesystem ..."

mount -t proc proc /proc

mount -t sysfs sysfs /sys

mount -o  remount,rw  / 

echo -e "Creating the files of device ..."

mdev -s 

echo -e "Mounting the filesystem ..."

mount -a

swapon -a

echo -e "Starting the log daemon ..."

syslogd

klogd

echo -e "Configuring loopback interface ..."

ifconfig  lo  127.0.0.1/24

ifconfig eth0 172.16.100.9/16

# END

而后讓此腳本具有執行權限:

chmod +x  etc/init.d/rc.sysinit

4、配置init及其所需要inittab文件

# cd  /mnt/sysroot

# rm  -f  linuxrc

為init進程提供配置文件:

# vim  etc/inittab

添加如下內容:

::sysinit:/etc/rc.d/rc.sysinit

console::respawn:-/bin/sh

::ctrlaltdel:/sbin/reboot

::shutdown:/bin/umount -a -r

5、為系統準備一個“文件系統表”配置文件/etc/fstab

# vim  etc/fstab

添加如下內容:

sysfs                   /sys                    sysfs   defaults        0 0

proc                    /proc                   proc    defaults        0 0

/dev/hda1               /boot                   ext3    defaults        0 0

/dev/hda2               /                       ext3    defaults        1 1

6、由于在rc.sysinit文件中啟動了日志進程,因此系統在運行中會產生大量日志并將其顯示于控制臺;這將會經常性的打斷正在進行的工作,為了避免這種情況,我們這里為日志進程建立配置文件,為其指定將日志發送至/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    MageEdu Linux (2.6.38.5)

    root (hd0,0)

    kernel /bzImage ro root=/dev/hda2 quiet

    initrd /initrd.gz

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

七、為新構建的ToyLinux啟用虛擬控制臺

這個可以通過宿主機來實現,也可以直接啟動剛構建成功的小Linux進行配置。我們這里采用通過宿主機的方式(重新啟動宿主機):

# cd /mnt/sysroot

將 etc/inittab文件改為如下內容:

::sysinit:/etc/init.d/rc.sysinit

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用戶的口令。您可以在目標主機啟動以后再動手更改root用戶的口令。

4、將 etc/inittab文件改為如下內容:

::sysinit:/etc/init.d/rc.sysinit

::respawn:/sbin/getty 9600 tty1

::respawn:/sbin/getty 9600 tty2

::respawn:/sbin/getty 9600 tty3

::respawn:/sbin/getty 9600 tty4

::respawn:/sbin/getty 9600 tty5

::respawn:/sbin/getty 9600 tty6

::shutdown:/bin/umount -a -r

::ctrlaltdel:/sbin/reboot

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

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

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

# vi  /etc/issue

添加如下內容:

Welcome to MageEdu Linux(http://www.magedu.com)...

Kernel \r

注:這里的內容可以根據你的需要進行修改。

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

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

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

# mkdir /etc/sysconfig

# vi  /etc/sysconfig/network

添加如下內容:

HOSTNAME=marion.example.com

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

# vi /etc/init.d/rc.sysinit

在文件尾部添加如下行:

HOSTNAME=

[ -e  /etc/sysconfig/network  && -r /etc/sysconfig/network ] && source /etc/sysconfig/network

[ -z ${HOSTNAME} ] && HOSTNAME="localhost"

/bin/hostname  ${HOSTNAME}

十一、通過dropbear為系統提供ssh遠程連接服務

注:以下過程在宿主機上實現。

1、編譯安裝dropbear

# tar xf dropbear-2013.56.tar.bz2 

# cd dropbear-2013.56

# ./configure 

# make

# make install

2、移植dropbear至目標系統

移植二進制程序及其依賴的庫文件,方能實現其在目標系統上正常運行。建議使用腳本進行(這里將其保存為bincp.sh),其會自動移植指定的命令及依賴的庫文件。

#!/bin/bash

#

read -t 30 -p "Target System Directory[/mnt/sysroot]: " DEST

DEST=${DEST:-/mnt/sysroot}

libcp() {

  LIBPATH=${1%/*}

  [ ! -d $DEST$LIBPATH ] && mkdir -p $DEST$LIBPATH

  [ ! -e $DEST${1} ] && cp $1 $DEST$LIBPATH && echo "copy lib $1 finished."

}

bincp() {

  CMDPATH=${1%/*}

  [ ! -d $DEST$CMDPATH ] && mkdir -p $DEST$CMDPATH

  [ ! -e $DEST${1} ] && cp $1 $DEST$CMDPATH

  for LIB in  `ldd $1 | grep -o "/.*lib\(64\)\{0,1\}/[^[:space:]]\{1,\}"`; do

    libcp $LIB

  done

}

read -p "Your command: " CMD

until [ $CMD == 'q' ]; do

   ! which $CMD && echo "Wrong command" && read -p "Input again:" CMD && continue

  COMMAND=` which $CMD | grep -v "^alias" | grep -o "[^[:space:]]\{1,\}"`

  bincp $COMMAND

  echo "copy $COMMAND finished."

  read -p "Continue: " CMD

done

接下來運行此腳本,分別輸入dropbear、dropbearkey和dbclient即可;這些命令會被存儲于目標系統的/usr/local/sbin或/usr/local/bin目錄中。

3、為遠程登錄的用戶提供偽終端設備文件

編輯/mnt/sysroot/etc/fstab,添加如下一行:

devpts /dev/pts devpts mode=620 0 0

創建所需要的目錄:

# mkdir /mnt/sysroot/dev/pts

4、為目標系統的dropbear生成主機密鑰

默認情況下,dropbear到/etc/dropbear目錄中查找使用的rsa格式主機密鑰(默認名稱為dropbear_rsa_host_key)和dss格式的主機密鑰(默認名稱為dropbear_dss_host_key)。其中,rsa格式可使用不同長度的密鑰,但dss格式只使用1024位的密鑰。

# mkdir /mnt/sysroot/etc/dropbear

# dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key -s 2048

# dropbearkey -t rsa -f /etc/dropbear/dropbear_dss_host_key

在生成rsa格式的key時,其長度指定部分-s 2048可以省略,也可以為其指定為其它長度,但長度需要為8的整數倍。

說明:此步驟也可以在目標主機上進行,但路徑要做相應的修改。

5、定義安全shell

安全起見,dropbear默認情況下僅允許其默認shell出現在/etc/shells文件中的用戶遠程登錄,因此,這里還需要創建/etc/shells文件,并添加所有允許的shell。

# cat >> /mnt/sysroot/etc/shells << EOF

/bin/sh

/bin/ash

/bin/hush

/bin/bash

EOF

6、為目標主機提供網絡服務轉換機制

在宿主機上使用默認選項編譯的dropbear將依賴nsswitch實現用戶名稱解析,因此,還需要為目標主機提供nss相關的庫文件及配置文件。

# cat >> /mnt/sysroot/etc/nsswitch.conf << EOF

passwd:     files

shadow:     files

group:      files

hosts:      files dns

EOF

復制所需要的庫文件:

# cp -d /lib/libnss_files*  /mnt/sysroot/lib/

# cp -d /usr/lib/libnss3.so /usr/lib/libnss_files.so /mnt/sysroot/usr/lib/

7、測試

啟動目標主機,設定好網絡屬性后,使用如下命令啟動dropbear服務即可。

# /usr/local/sbin/dropbear

接下來就可以遠程進行連接測試了。

十二、通過nginx提供web服務

1、在宿主機編譯安裝nginx-1.2.5

# tar nginx-1.2.5.tar.gz

# cd nginx-1.2.5

# ./configure --prefix=/usr/local --conf-path=/etc/nginx/nginx.conf  --error-log-path=/var/log/nginx/error.log --user=nginx --group=nginx --http-log-path=/var/log/nginx/access.log  --without-pcre --without-http_rewrite_module --without-http_geo_module --without-http_fastcgi_module  --without-http_uwsgi_module  --without-http_scgi_module --without-http_memcached_module --without-http_upstream_ip_hash_module --without-http_upstream_least_conn_module  --without-http_upstream_keepalive_module --http-log-path=/var/log/nginx

# make

# make install

2、移植nginx至目標系統

(1) 移植二進制程序及其依賴的庫文件,方能實現其在目標系統上正常運行。建議使用前面的bincp.sh腳本進行。

(2) 移植配置文件至目標系統

# mkdir  /mnt/sysroot/etc/nginx/

# cp /etc/nginx/{nginx.conf,mime.types}  /mnt/sysroot/etc/nginx/

(3) 移植測試頁面至目標系統,當然,也可以不采用下面的步驟而在目標系統上直接創建。

# mkdir /mnt/sysroot/usr/local/

# cp -r /usr/local/html  /mnt/sysroot/usr/local/

3、測試

啟動目標主機,首先配置好網絡屬性,并使用adduser為其添加nginx用戶和nginx組。

然后使用如下命令啟動nginx,即可通過瀏覽器測試訪問。

# /usr/local/nginx

【騰訊云】云服務器、云數據庫、COS、CDN、短信等云產品特惠熱賣中

發表評論

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前評論:1   其中:訪客  0   博主  0

    • avatar 貓咪 0

      很不錯的樣子⊙0⊙