嵌入式之Linux系統裁剪和定制---(kernel+busyboxy+dropbear+nginx)


 

本文將介紹通過完全手動定制內核,在此基礎上添加 busybox ,並實現遠程登陸,使裁剪的 linux 能夠運行 nginx 。

在此之前介紹一下 linux 系統的啟動流程。

linux系統啟動流程
POST-->BIOS(BOOT Sequence)-->MBR(bootloader,446個字節)-->kernel-->initrd(initramfs)-->(ROORFS)/sbin/init(/etc/inittab)

注:以上linux啟動流程只是針對於centos6系列基於upstart流程的2.6內核,centos7使用了stytemd和此稍有不同。

關於啟動流程詳情參考另外一片文章:http://www.cnblogs.com/sysk/p/4778976.html

 

開始:

為虛擬機准備一塊 1G (大小自定)的硬盤 為新的硬盤分區

/dev/sdb1=50M 剩余的容量全部給 /dev/sdb2

echo -e "n \n p \n 1 \n \n +50M \n n \n p \n 2 \n \n \n w \n" |fdisk /dev/sdb

查看結果:

Device Boot           Start         End      Blocks   Id  System

/dev/sdb1               1           7       56196   83  Linux

/dev/sdb2               8         130      987997+  83  Linux

格式化分區

mke2fs  -t ext4 /dev/sdb1

mke2fs  -t ext4 /dev/sdb2

安裝 grub 引導程序

mkdir /mnt/boot

mkdir /mnt/sysroot

掛載 /dev/sdb1  到  /mnt/boot

mount /dev/sdb1 /mnt/boot

grub-install --root-directory=/mnt /dev/sdb

執行結果如下

[root@localhost ~]# grub-install --root-directory=/mnt /dev/sdb

Probing devices to guess BIOS drives. This may take a long time.

Installation finished. No error reported.

This is the contents of the device map /mnt/boot/grub/device.map.

Check if this is correct or not. If any of the lines is incorrect,

fix it and re-run the script `grub-install'.

(fd0) /dev/fd0

(hd0) /dev/sda

(hd1) /dev/sdb

查看是否安裝成功

[root@localhost ~]# ls /mnt/boot/grub/

device.map fat_stage1_5 iso9660_stage1_5 minix_stage1_5 stage1ufs2_stage1_5    xfs_stage1_5

e2fs_stage1_5  ffs_stage1_5  jfs_stage1_5      reiserfs_stage1_5  stage2  vstafs_stage1_5

查看自己的硬件類型(我是基於VM10的)

[root@localhost ~]# lspci

00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)

00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]

00:01.1 IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)

00:02.0 VGA compatible controller: InnoTek Systemberatung GmbH VirtualBox Graphics Adapter

00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)

00:04.0 System peripheral: InnoTek Systemberatung GmbH VirtualBox Guest Service

00:05.0 Multimedia audio controller: Intel Corporation 82801AA AC'97 Audio Controller (rev 01)

00:06.0 USB controller: Apple Inc. KeyLargo/Intrepid USB

00:07.0 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08)

00:14.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI

 

編譯內核:

安裝必要的開發工具和依賴包:

yum install perl
yum install bc
yum insatll gcc-c++
yum install ncurses-devel
yum groupinstall "Development Libraries" " Development Tools"

下載內核源碼后開始:

[root@localhost ~]# ln -sv /usr/src/linux-3.12.26/ /usr/src/linux

`/usr/src/linux' -> `/usr/src/linux-3.12.26/'

[root@localhost ~]# cd /usr/src/linux

[root@localhost linux]# ls

arch   COPYING  crypto  drivers   fs       init  Kbuild   kernel  MAINTAINERS  mm   README   samples  security  tools  virt

block  CREDITS  Documentation  firmware  include  ipc   Kconfig  lib     Makefile     net  REPORTING-BUGS  scripts  sound  usr

[root@localhost linux]# make allnoconfig

HOSTCC  scripts/basic/fixdep

HOSTCC  scripts/kconfig/conf.o

SHIPPED scripts/kconfig/zconf.tab.c

SHIPPED scripts/kconfig/zconf.lex.c

SHIPPED scripts/kconfig/zconf.hash.c

HOSTCC  scripts/kconfig/zconf.tab.o

HOSTLD  scripts/kconfig/conf

scripts/kconfig/conf --allnoconfig Kconfig

#

# configuration written to .config

#
[root@localhost linux]# make menuconfig

下面開始配置所有功能直接編譯進內核

 

 

 

進入 General setup  選項

返回首界面進入 Processor type and features

進入 Processor family (Generic-x86-64) 選擇 cpu 類型 默認即可

返回首界面進入 Bus options (PCI etc.)

返回首界面進入  Executable file formats / Emulations

返回首界面進入 Networking support --->  Networking options  

返回首界面進入  Device Drivers  --->Generic Driver Options

返回上級界面

進入scsi device support

返回上級進入 Network device support--->   Ethernet driver support (NEW)

返回到 Network device support 此界面下選擇 Input device suppor t

返回上級添加 usb 支持  USB support

返回首界面 File systems 

退出保存配置

[root@localhost linux]# make

[root@localhost linux]# make bzImage

make[1]: Nothing to be done for `all'.

make[1]: Nothing to be done for `relocs'.

CHK     include/config/kernel.release

CHK     include/generated/uapi/linux/version.h

CHK     include/generated/utsrelease.h

CALL    scripts/checksyscalls.sh

CHK     include/generated/compile.h

make[3]: `arch/x86/realmode/rm/realmode.bin' is up to date.

Kernel: arch/x86/boot/bzImage is ready  (#1)

[root@localhost linux]# cp ./arch/x86/boot/bzImage /mnt/boot

[root@localhost linux]# ls /mnt/boot/

bzImage  grub  lost+found

 

為新系統添加 rootfs  及 二進制程序 由 busybox 提供

[root@localhost ~]# tar -xf busybox-1.22.1.tar.bz2 -C /usr/src/

[root@localhost ~]# ls /usr/src/

busybox-1.22.1  linux  linux-3.12.26

busybox-1.22.1.tar.bz2  glibc-static-2.12-1.132.el6.x86_64.rpm  mariadb-5.5.36-linux-x86_64.tar.gz

[root@localhost ~]# cd /usr/src/busybox-1.22.1/

[root@localhost busybox-1.22.1]# ls

applets     configs        editors    libbb       Makefile.custom  printutils  shell

 

編譯 busybox

[root@localhost linux-3.12.26]# make menuconfig

進入 Busybox Settings ---->Build Options

此處需要選擇 

Busybox Settings --> Build Options -->  Build BusyBox as a static binary (no shared libs)

安裝glibc靜態支持

yum install glibc-static
[root@localhost busybox-1.22.1]# make

[root@localhost busybox-1.22.1]# make install

 

此時會在當前目錄生成 _install 目錄

[root@localhost busybox-1.22.1]# ls _install/

bin  linuxrc  sbin  usr

 

掛載 /dev/sdb2  到   /mnt/sysroot

[root@localhost busybox-1.22.1]# mount /dev/sdb2 /mnt/sysroot/

[root@localhost busybox-1.22.1]# cp -a ./_install/*  /mnt/sysroot/

[root@localhost busybox-1.22.1]# ls /mnt/sysroot/

bin  linuxrc  lost+found  sbin  usr

[root@localhostbusybox-1.22.1]#mkdir -pv /mnt/sysroot/{etc,root,mnt,media,proc,sys,dev,home,lib,lib64,var,tmp}

 

由於 busybox 啟動時默認的 init 程序為 /etc/init.d/rcS

[root@localhost busybox-1.22.1]# mkdir -pv /mnt/sysroot/etc/init.d

mkdir: created directory `/mnt/sysroot/etc/init.d'

[root@localhost busybox-1.22.1]# vim /mnt/sysroot/etc/init.d/rcS

#!/bin/sh

mount -n -t ext4 -o remount,rw /dev/sda2 /

mount -n -t ext4 /dev/sda1 /boot

mount -n -t tmpfs none /dev

mount -n -t proc proc  /proc

mount -n -t sysfs sysfs /sys

mkdir /dev/pts/

mount -n -t devpts devpys /dev/pts

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

if [ ! -z $HOSTNAME ];then

/bin/hostname $HOSTNAME

else

/bin/hostname localhost

fi

 

[root@localhost busybox-1.22.1]# vim /mnt/sysroot/etc/profile

export PS1="[\u@\h \w]\$"

[root@localhost linux]# mkdir -pv /mnt/sysroot/etc/sysconfig

mkdir: created directory `/mnt/sysroot/etc/sysconfig'

[root@localhost linux]# vim /mnt/sysroot/etc/sysconfig/network

HOSTNAME=www.mylinux.com

 

編輯 grub 配置文件

[root@localhost busybox-1.22.1]# vim /mnt/boot/grub/grub.conf

default=0

timeout=5

title busy-box-1.0

root(hd0,0)

kernel /bzImage ro root=/dev/sda2

 

先測試下看能否啟動

下面使其能夠以用戶名密碼進行登錄

[root@localhost ~]# vim /mnt/sysroot/etc/inittab

::sysinit:/etc/init.d/rcS

tty1::respawn:/sbin/getty 19200 tty1

tty2::respawn:/sbin/getty 19200 tty2

 

為其提供 /etc/passwd /etc/shadow /etc/group /etc/gshadow

直接從當前系統復制

[root@localhost ~]# cp -p /etc/passwd /mnt/sysroot/etc/

[root@localhost ~]# cp -p /etc/shadow /mnt/sysroot/etc/

[root@localhost ~]# cp -p /etc/group /mnt/sysroot/etc/

[root@localhost ~]# cp -p /etc/gshadow /mnt/sysroot/etc/

 也可以將上面四個文件分別用grep復制過去 如果嫌棄本機這些文件里面太多東西的話

 

grep  "^root"  /etc/shadow  > mnt/sysroot/etc/shadow

 

編輯 /mnt/sysroot/etc/passwd  將登錄 shell 改為 /bin/sh

測試是否成功

正常登錄

下面為其提供遠程連接功能

編譯安裝 dropbear ( ssh )

為了進行登錄名解析需要  linss 庫文件和 /etc/nsswitch.conf

啟用網絡功能

[root@localhost ~]# cd dropbear-2014.65

./configure

make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"

[root@localhost dropbear-2014.65]# make install

 

默認安裝在 /usr/local/{bin,sbin }

將此應用移植到目標系統移植腳本如下

#!/bin/bash
#
 
MntDIR1="/mnt/boot"
 
MntDIR2="/mnt/sysroot"
 
PORAPP ()
 
{
 
  read -p "Plz input the app: " APPLI
 
  until [ "$APPLI" == quit ];do
 
        while true;do
 
            if  which --skip-alias $APPLI ;then
 
                WHERE=$(which --skip-alias $APPLI)
 
                DIRAPP=$(dirname $WHERE)
 
                [ -d ${MntDIR2}${DIRAPP} ]||mkdir -p ${MntDIR2}${DIRAPP}
 
                [ -e ${MntDIR2}${WHERE} ]||cp $WHERE ${MntDIR2}${DIRAPP}
 
                LIBS=$(ldd $WHERE|grep -oE "(/[[:alnum:]]*/[^[:space:]]*[[:space:]])")
 
                for i in $LIBS;do
 
                    DIRLIB=$(dirname $i)
 
                    [ -d ${MntDIR2}$DIRLIB ]||mkdir -p ${MntDIR2}$DIRLIB
 
                    cp $i ${MntDIR2}$i
 
                done
 
               read -p "Do you want to another app? or quit: " APPLI
 
               continue 2
 
            else
 
                read -p "Input is not app!! Plz input again or quit: " APPLI
 
                continue 2
 
            fi
 
          done
 
 done
 
}
 
##################MAIN##################
 
MAIN ()
 
{
 PORAPP
 
}
 
MAIN

 

運行腳本

[root@localhost dropbear-2014.65]# bash 123.sh

bash: 123.sh: No such file or directory

[root@localhost dropbear-2014.65]# bash /root/123.sh

Plz input the app: /usr/local/bin/dbclient         

/usr/local/bin/dbclient

Do you want to another app? or quit: /usr/local/bin/dropbearkey

/usr/local/bin/dropbearkey

Do you want to another app? or quit: /usr/local/bin/dropbearconvert 

/usr/local/bin/dropbearconvert

Do you want to another app? or quit: /usr/local/sbin/dropbear

/usr/local/sbin/dropbear

Do you want to another app? or quit: quit

 

查看移植結果

[root@localhost dropbear-2014.65]# ls /mnt/sysroot/usr/local/{bin,sbin}

/mnt/sysroot/usr/local/bin:

dbclient  dropbearconvert  dropbearkey

/mnt/sysroot/usr/local/sbin:

dropbear

[root@localhost dropbear-2014.65]# ls /mnt/sysroot/lib64/

ld-linux-x86-64.so.2  libcrypt.so.1  libc.so.6  libdl.so.2  libfreebl3.so  libutil.so.1  libz.so.1

 

創建主機密鑰

[root@localhost dropbear-2014.65]# mkdir /mnt/sysroot/etc/dropbear

[root@localhostdropbear-2014.65]#

dropbearkey-t dss -f /mnt/sysroot/etc/dropbear/dropbear_dss__host_key

[root@localhost dropbear-2014.65]# 

dropbearkey -t rsa -f /mnt/sysroot/etc/dropbear/dropbear_rsa__host_key

 

移植 linss 庫

[root@localhost dropbear-2014.65]# find  /lib64/libnss* -exec cp {} /mnt/sysroot/lib64/ \;

[root@localhost dropbear-2014.65]# find  /usr/lib64/libnss* -exec cp {} /mnt/sysroot/usr/lib64/ \;

 

創建 /etc/nsswitch.conf

passwd:     files

shadow:     files

group:      files

 

編輯 /etc/init.d/rcS 添加如下內容

ifconfig eth0 192.168.253.22 netmask 255.255.255.0 up

ifconfig lo  127.0.0.0      netmask 255.0.0.0  

 

/usr/local/sbin/dropbear -E  驗證

移植 nginx 到目標機

編譯安裝

./confgiure --prefix=/usr/local/nginx --without-httpd_rewrite_module

make && make install 

 

運行移植腳本輸入 /usr/local/nginx/sbin/nginx

cp -a -r /usr/local/nginx/* /mn t/sysroot/usr/local/nginx/

完成測試

客戶端訪問測試

整個過程完畢

 

 

 

 

遇到的問題:

在做完整個系統之后重啟出現了這個報錯

VFS: Cannot open root device "sda2" or unknown-block(0,0)
Please append a correct "root=" boot option;here are the available partition 0b00   1048575 sr0 driver: sr
kernal panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

搞了好幾天最后終於找到原因:

找到虛擬機配置文件的“.vmx",vmware默認的是LSI Logic,找到 ".vmx" 文件 里的scsi0.virtualDev = "lsilogic" 
改為 scsi0.virtualDev = "buslogic“

詳情參照一下摘抄:

這兩天一直在安裝lfs6.2,安裝到最后編譯完內核,修改完fstab,最后安裝grub后,啟動lfs報錯提示   
VFS:Cannot open root device "sda" or unknow-block(0,0)
Please append a correct "root=" boot option
kernel panic:VFS:Unable to mount root fs on unknown-block(0,0) 
看到這個錯誤的時候,我快崩潰了,我等了這么久,到最后一步出現了這個錯誤。大概意思是沒有把root文件系統所在的硬盤控制器的驅動編譯到內核中去,編譯的時候我選擇了scsi驅動了很奇怪,於是開始goole,baidu得到結果,大多都是集中在:
Device Drivers--->SCSI device support--->SCSI disk support
Device Drivers--->SCSI device support--->SCSI low-level drivers--->BusLogic SCSI support 


一、磁盤(!!!)
        在選擇模塊前,要先弄清楚VMware虛擬機的硬件類型,下面這個表是VMware6中自定義虛擬機配置時給出的配置,不難發現當您使用 VMware推薦向導給出的配置時,實際使用的是SCSI類型設備中的LSI Logic設備。這里要注意的一個地方是,既然有兩個SCSI設備能夠供其選擇,那么該如何判斷呢?很簡單,因為他是通過內核主版本號來划分的。感興趣的 朋友能夠通過新建虛擬機Custom-Linux下Version列表中Other Linux2.6.X kernel 和 Other Linux2.4.X kernel來比較。2.4內核之前使用BusLogic,2.6內核使用的是  LSI Logic 。
       VMware 6.0:
            I/O ADapter Types
                IDE adapter: ATAPI
              SCSI adapter: BusLogic
                                 LSI Logic
這是Other Linux2.6.X kernel配置系統信息
00:10.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)
  
這是Other Linux2.4.X kernel配置系統信息
00:10.0 SCSI storage controller: BusLogic BT-946C (BA80C30) [MultiMaster 10] (rev 01)
    現在分別介紹模塊選擇路徑
    這個是SCSI磁盤設備模塊,必須選擇。
    Linux Kernel Configuration
        -> Device Drivers
            -> SCSI device support
                - > SCSI disk support
    這個是BusLogic設備驅動模塊。使用這個設備的的朋友需要選取。 Linux Kernel Configuration -> Device Drivers
            -> SCSI device support
              -> SCSI low-level drivers
                 -> BusLogic SCSI support    (這里一定要選上)
    這個是LSI Logic設備驅動模塊。使用這個設備的的朋友需要選取。
    Linux Kernel Configuration
       -> Device Drivers 
           -> Fusion MPT device support
                -> Fusion MPT (base + ScsiHost) drivers 

我的內核是kernel-2.6.16.27,但是安裝了上面提示的Fusion MPT (base + ScsiHost) drivers。問題依舊存在.所以我修改虛擬機的“.vmx",vmware默認的是LSI Logic,找到 ".vmx" 文件 里的scsi0.virtualDev = "lsilogic" 
改為 scsi0.virtualDev = "buslogic
從新編譯內核,啟動系統`終於跳過了

 

另一個問題是關於網卡的:

  這個設備和內核版本沒有關系,下面是系統信息參考:

02:00.0 Ethernet controller: Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE] (rev 10)
  
  Linux Kernel Configuration
  -> Device Drivers
    -> Networking support
       -> Ethernet (10 or 100Mbit)

             -> [*] EISA, VLB, PCI and on board controllers 
              ->   <*> AMD PCnet32 PCI support

              ->   <*> AMD 8111 (new PCI lance) support 

 

VMWare 所支持的網卡類型
它默認是虛擬的AMD PCNet AM79C970A網卡,但也可以改變網卡配置,虛擬出Intel(R) PRO/1000和VMware PCI Ethernet Adapter網卡。

如果在.vmx文件中用如下語句指定:

ethernet0.virtualDev = "e1000"

其值為e1000指定網卡類型為Intel(R) PRO/1000

其值為vlance指定網卡類型為AMD PCNet AM79C970A(默認為此項)

其值為vmxnet指定網卡類型為VMware PCI Ethernet Adapter

 

我的網卡就是沒有識別,在vm配置文件中加上

ethernet0.virtualDev = "e1000"
就可以識別到網卡了。
 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM