1:以下的實現過程都使用VM虛擬機,在這上面實現的。
2:實現打造屬於自己的Linux系統,其實用的是將現有的完整的Linux系統精簡,然後打包做成不到10M的系統。
3:我所用的Linux系統爲Redhat Enterprise Linux 5(內核爲 2.6.18)
=======================================================================
首先,我們要知道,一個linux的系統之所以能夠啓動,需要什麼?
1.需要一個boot loader,以確保能夠帶起硬盤
2.需要一個內核。(廢話-。-)
3.需要一個小型的能夠加載內核文件系統的程序(initrd)
4.需要一個能夠定義如何啓動的文件(inittab)
5.需要inittab中供啓動的rc.sysinit文件
其實,一個linux能夠啓動,需要的也就是這麼多,那接下來,我們開始一步步着手準備!
-----------------------------------------------------------------------------------------------------------------------------
第一步:準備工作,並創建引導文件!
既然我們需要boot loader能夠帶起硬盤,那麼我們總要先有個硬盤吧?
好,調用虛擬機,給我們的現有的linux額外增加一塊新硬盤,這塊硬盤可以不用太大,夠用就好,比如?嗯……8G,夠你用了吧?
點擊Add,添加一塊新的硬盤,設置大小爲8G,其他默認,然後點ok~
進入我們的Linux系統。使用fdisk -l 命令,我們看到了一塊完整的未經開墾的硬盤:
- Disk /dev/sdc: 8589 MB, 8589934592 bytes
- 255 heads, 63 sectors/track, 1044 cylinders
- Units = cylinders of 16065 * 512 = 8225280 bytes
- Device Boot Start End Blocks Id System
它的名字叫/dev/sdc於是,我們開始給他分區,首先我們要給他分一塊主分區,專門放置我們的小系統的內核等重要的文件。
然後我們要分一塊稍微大一點的分區,這是我們的應用分區,我們以後所有的各種文件都將放在這個分區裏。
使用fdisk /dev/sdc 設置我們硬盤的各個分區之後,確認,於是硬盤成了這個樣子:
- Disk /dev/sdc: 8589 MB, 8589934592 bytes
- 255 heads, 63 sectors/track, 1044 cylinders
- Units = cylinders of 16065 * 512 = 8225280 bytes
- Device Boot Start End Blocks Id System
- /dev/sdc1 1 13 104391 83 Linux
- /dev/sdc2 14 136 987997+ 83 Linux
好的~,我們將其格式化成ext3文件系統,然後分別將兩塊硬盤掛載在我們新建的兩個目錄上,1.我們將/dev/sdc1掛載在/mnt/root中(這就是我們的存放內核等重要文件的分區)
2.我們將/dev/sdc2掛載在/mut/sysroot下(而這個,就是我們日常應用的分區)
好的,接下來。我們就要開始將boot loader,整個磁盤的引導信息寫入我們新的硬盤中了。
Linux爲我們提供了grub這個好用的寫入也是讀取更是引導程序。我們只需要使用命令:
- [[email protected] ~]# grub-install --root-directory=/mnt /dev/sdc
即可將grub安裝在了我們的sdc上,並且默認給他的目錄是/mnt。爲什麼是/mnt而不是/mnt/boot呢?因爲 grub安裝後,會自動在那個磁盤的根目錄下創建/boot目錄,所以我們只需要指定它的父目錄,即/mnt即可。
於是,我們看看剛纔安裝的/mnt下有
- total 14
- drwxr-xr-x 2 root root 1024 Aug 3 07:45 grub
- drwx------ 2 root root 12288 Aug 3 07:42 lost+found
而進入grub裏,則是已經安裝在我們這裏的文件
- total 197
- -rw-r--r-- 1 root root 60 Aug 3 07:45 device.map
- -rw-r--r-- 1 root root 7584 Aug 3 07:45 e2fs_stage1_5
- -rw-r--r-- 1 root root 7456 Aug 3 07:45 fat_stage1_5
- -rw-r--r-- 1 root root 6720 Aug 3 07:45 ffs_stage1_5
- -rw-r--r-- 1 root root 6720 Aug 3 07:45 iso9660_stage1_5
- -rw-r--r-- 1 root root 8192 Aug 3 07:45 jfs_stage1_5
- -rw-r--r-- 1 root root 6880 Aug 3 07:45 minix_stage1_5
- -rw-r--r-- 1 root root 9248 Aug 3 07:45 reiserfs_stage1_5
- -rw-r--r-- 1 root root 512 Aug 3 07:45 stage1
- -rw-r--r-- 1 root root 104988 Aug 3 07:45 stage2
- -rw-r--r-- 1 root root 7072 Aug 3 07:45 ufs2_stage1_5
- -rw-r--r-- 1 root root 6272 Aug 3 07:45 vstafs_stage1_5
- -rw-r--r-- 1 root root 8904 Aug 3 07:45 xfs_stage1_5
----------------------------------------------------------------------------------------------------
第二步 :搞定內核的相關配置。
好的,我們的硬盤已經準備好了,那麼內核怎麼辦呢?這裏我們使用Redhat自帶的內核
它在/boot目錄下,名字叫「vmlinuz-2.6.18-164.el5」。
我們用cp複製命令直接將其複製到我們的主分區下,並命名爲一個簡單的不帶版本號得名字vmlinuz:
- [[email protected] grub]# cp /boot/vmlinuz-2.6.18-164.el5 /mnt/boot/vmlinuz
之後,我們的內核有了,但是拿什麼來調用它呢?這就需要Redhat中的一個能在內存上加載的驅動根目錄文件系統的一個文件了:它就是:lintrd.
它在/root/下靜靜的放着。每當系統需要啓動的時候就會悄悄的執行一下。
用file命令查看它發現他是個gzip文件。
- [[email protected] linuxmini]# file initrd-2.6.18-164.el5.img
- initrd-2.6.18-164.el5.img: gzip compressed data, from Unix, last modified: Wed Jul 20 15:23:58 2011, max compression
好吧,雖然它的確是img格式結尾的,但那不影響我們發現他的僞裝,於是我們改名後用gunzip將其解壓:
- [[email protected] linuxmini]# mv initrd-2.6.18-164.el5.img initrd-2.6.18-164.el5.img.gz
解壓後的我們再用file命令查看它,發現它又變成了一個cpio文件
- [[email protected] linuxmini]# gunzip initrd-2.6.18-164.el5.img.gz
cpio文件是一種古老的歸檔工具,它可以原封不動的將多個文件歸檔,在製作光盤鏡像的時候尤其有用。
- [[email protected] linuxmini]# file initrd-2.6.18-164.el5.img
- initrd-2.6.18-164.el5.img: ASCII cpio archive (SVR4 with no CRC)
那麼我們使用cpio的命令將它展開:
終於,我們看到了它的真正明面,ll一下:
- [[email protected] linuxmini]# cpio -id < initrd-2.6.18-164.el5.img
看到了麼,這就是一個這樣精簡的加載在內存裏的用來臨時充當系統的文件。
- [[email protected] linuxmini]# ll
- total 68
- drwx------ 2 root root 4096 Aug 3 07:58 bin
- drwx------ 3 root root 4096 Aug 3 07:58 dev
- drwx------ 3 root root 4096 Aug 3 07:58 etc
- -rwx------ 1 root root 2861 Aug 3 07:59 init
- drwx------ 3 root root 4096 Aug 3 07:58 lib
- drwx------ 2 root root 4096 Aug 3 07:58 proc
- lrwxrwxrwx 1 root root 3 Aug 3 07:58 sbin -> bin
- drwx------ 2 root root 4096 Aug 3 07:58 sys
- drwx------ 2 root root 4096 Aug 3 07:58 sysroot
我們需要修改一些參數以被我們使用:
用vim打開init這個文件。在最下面找到一行:
這個是最後要引導的硬盤分區目錄。
- mkrootdev -t ext3 -o defaults,ro /dev/vol0/root
我們因爲要打造自己的,所以需要改成引導我們自己的
於是:
如果你問,爲什麼是sda2而不是sdc2,那麼我要說的是,因爲我們這個系統是最後要移植到其他的機器上的, 那時候,對於那個機子來說,我們這裏的sdc2會在那裏被識別成sda2,所以我們索性直接將其改爲sda2就好。
- mkrootdev -t ext3 -o defaults,ro sda2
修改完後,我們要將其重新打包:我們將其打包,並直接寫成了initrd.gz並放在/mnt/boot下。
- [[email protected] linuxmini]# find . | cpio -H newc -o --quiet | gzip -9 > /mnt/boot/initrd.gz
好的,我們看一下此時此刻我們創建的主分區到底有哪些東西:
嗯,主分區基本上就這樣了。
- total 5.0M
- drwxr-xr-x 2 root root 1.0K Aug 3 07:47 grub
- -rw-r--r-- 1 root root 3.2M Aug 3 08:01 initrd.gz
- drwx------ 2 root root 12K Aug 3 07:42 lost+found
- -rw-r--r-- 1 root root 1.8M Aug 3 07:48 vmlinuz
第三步:搞定工作分區,搞定啓動流程,搞定各項文件。
進入工作分區/mnt/sysroot/創建那些真正linux中的文件夾:
- [[email protected] sysroot]# mkdir {bin,sbin,usr/{bin,sbin},proc,sys,home,root,mnt,media,var,lib,etc,dev,boot,tmp} -pv
我們有各種文件夾之後,就需要考慮系統啓動需要的那個主進程init:
- [[email protected] sysroot]# ls
- bin dev home lost+found mnt root sys usr
- boot etc lib media proc sbin tmp var
將這個文件複製到我們的/sbin目錄下。
- [[email protected] sysroot]# cp /sbin/init /mnt/sysroot/sbin/
其實它就是我們的主shell,但是運行它還需要很多鏈接庫文件,它們都在/lib目錄下,我們爲了能在微型系統上也運行,則需要將它所需要的那些庫文件都一一的複製過來。於是:我們使用:ldd命令來查看到底init需要什麼庫文件:
我們需要將這些庫文件一一複製進我們自己的/lib目錄裏。
- [[email protected] sysroot]# ldd /sbin/init
- linux-gate.so.1 => (0x00ccb000)
- libsepol.so.1 => /lib/libsepol.so.1 (0x0021d000)
- libselinux.so.1 => /lib/libselinux.so.1 (0x00203000)
- libc.so.6 => /lib/libc.so.6 (0x004cb000)
- libdl.so.2 => /lib/libdl.so.2 (0x00613000)
- /lib/ld-linux.so.2 (0x004a8000)
之後我們有了主進程,還需要我們的bash命令,同理,我們也將/bin/bash複製進我們自己的/bin/目錄裏。並用ldd命令查看bash需要什麼樣的庫文件,然後一一複製進去。則:
- [[email protected] sysroot]# cp /lib/libsepol.so.1 /mnt/sysroot/lib/
- [[email protected] sysroot]# cp /lib/libselinux.so.1 /mnt/sysroot/lib/
- [[email protected] sysroot]# cp /lib/libc.so.6 /mnt/sysroot/lib/
- [[email protected] sysroot]# cp /lib/libdl.so.2 /mnt/sysroot/lib/
- [[email protected] sysroot]# cp /lib/ld-linux.so.2 /mnt/sysroot/lib/
有了bash,可以說我們已經完全可以進入自己的小系統了。但是系統啓動後是先運行sh的,那麼我們沒有sh怎麼辦?不復制了,我們直接將sh連接成bash,等於讓他啓動就直接使用bash。則,我們做一個鏈接:
- [[email protected] sysroot]# cp /bin/bash /mnt/sysroot/bin/
- [[email protected] sysroot]# ldd /bin/bash
- linux-gate.so.1 => (0x005ff000)
- libtermcap.so.2 => /lib/libtermcap.so.2 (0x00642000)
- libdl.so.2 => /lib/libdl.so.2 (0x00613000)
- libc.so.6 => /lib/libc.so.6 (0x00110000)
- /lib/ld-linux.so.2 (0x004a8000)
- [[email protected] sysroot]# cp /lib/libtermcap.so.2 /mnt/sysroot/lib/
此時,我們ll看一下我們的/bin目錄,則已經有了一個鏈接文件,sh -> bash。這時,我們的小系統可以說已經是可以運行了。
- [[email protected] bin]# ln -sv bash sh
- create symbolic link `sh' to `bash'
- [[email protected] bin]# ll
- total 732
- -rwxr-xr-x 1 root root 735004 Aug 3 08:08 bash
- lrwxrwxrwx 1 root root 4 Aug 3 08:10 sh -> bash
但是,進去之後我們什麼都不能幹,只能做一些bash的內部命令,比如……cd...echo.....等等,所以我們還想加入一個ls命令,能夠查看目錄。
那麼這時的你是否會如何往自己的系統內加入一個命令呢?
是的,複製那個/bin或者/sbin下的你要的那個命令到我們自己的/bin或者/sbin下,然後用ldd命令查看運行這個命令需要的基本庫文件,然後再將庫文件一一複製就好。
那麼添加ls命令的過程應該是這樣的:
此時的你,可以考慮使用
- [[email protected] ~]# cp /bin/ls /mnt/sysroot/bin/
- [[email protected] ~]# ldd /bin/ls
- linux-gate.so.1 => (0x00b9f000)
- librt.so.1 => /lib/librt.so.1 (0x0065b000)
- libacl.so.1 => /lib/libacl.so.1 (0x00666000)
- libselinux.so.1 => /lib/libselinux.so.1 (0x00203000)
- libc.so.6 => /lib/libc.so.6 (0x004cb000)
- libpthread.so.0 => /lib/libpthread.so.0 (0x00642000)
- /lib/ld-linux.so.2 (0x004a8000)
- libattr.so.1 => /lib/libattr.so.1 (0x00265000)
- libdl.so.2 => /lib/libdl.so.2 (0x00613000)
- libsepol.so.1 => /lib/libsepol.so.1 (0x0021d000)
- [[email protected] ~]# cp /lib/librt.so.1 /mnt/sysroot/lib/
- [[email protected] ~]# cp /lib/libacl.so.1 /mnt/sysroot/lib/
- [[email protected] ~]# cp /lib/libpthread.so.0 /mnt/sysroot/lib/
- [[email protected] ~]# cp /lib/libattr.so.1 /mnt/sysroot/lib/
「chroot /mnt/sysroot/ 」這條命令,進入自己的小系統悄悄的看看喲,而且還是可以使用ls命令的喲!
呵呵,那麼如何讓他能夠隨開機啓動呢?
第四步:搞定開機啓動的各項配置:
開機需要讀取/etc/inittab所以我們進入我們的小系統手動創建一個inittab文件:
在裏面寫入:
- [[email protected] ~]# cd /mnt/sysroot/etc/
- [[email protected] etc]# vim inittab
這定義了開機之後以第3中模式(即命令行模式進入系統)
- id:3:initdefault
- si::sysinit:/etc/rc.d/rc.sysinit
並啓動系統sysinit,而如何啓動呢?在/etc/rc.d/rc.sysinit中定義:於是我們又需要手動創建/etc/rc.d/rc.sysinit文件
創建相關目錄並創建文件:rc.sysinit
進入文件,寫入:這是定義了系統啓動後好後,顯示的內容,以及啓用的shell是什麼,我們這裏讓他直接/bin/bash
- #!/bin/bash
- echo -e "===================================="
- echo -e " \033[31mWelcome to WeiYan's Little Linux\033[0m"
- echo -e "===================================="
- /bin/bash
寫好這個之後,保存退出,別忘了給它執行權限:
最後,我們就要定義,系統如何啓動了。
- [[email protected] rc.d]# chmod +x rc.sysinit
- [[email protected] rc.d]# ll
- total 8
- -rwxr-xr-x 1 root root 178 Aug 3 08:24 rc.sysinit
進入/mnt/boot/grub下,找到grub.conf,這個文件定義了開機加電自檢之後,系統讀取了bootloarder,如何去加載內核等相關信息:
我們修改它:
這句定義了root在哪個磁盤,內核在哪裏,內核的root目錄在哪,使用什麼來啓動內核。這些信息。
- default=0
- timeout=10
- title WeiYan's Little Linux
- root (hd0,0)
- kernel /vmlinuz ro root=/dev/sda2
- initrd /initrd.gz
當你定義到這的時候,可以說
你已經大功告成了!接下來,我們就要真正的將這塊磁盤予以應用了!
最後一步:實現吧!夢想的少年!
我們新建一個虛擬系統,使用自定義設置,默認workstation 6.
選擇另外版本2.6內核的linux。
在自己制定路徑,選擇核心,選擇分配給的內存大小之後。進入選擇硬盤的階段,我們選擇,使用一塊已有的硬盤:
下一步,選擇我們之前掛載在真正linux上的那個硬盤。
好的,點擊完成。
接下來,就可以啓動我們的小linux了!
經過一系列的內部運行,終於:我們看到了我們自己製作的linux~!
到這裏,我們的所有工作都已經做完了,你已經創建出了一個屬於自己的,大小不足10M的linux操作系統!!
而且這個系統裏還有ls這個外部命令!