打造自己的linux--認識啓動過程
看一下linux具體的啓動過程,下面是一個分析圖:
1. 第一階段:開機自檢 ->MBR引導
2. 第二階段:選擇硬盤啓動/boot/grub/目錄,當MBR引導時會看到引導菜單即grub 菜單,grub選擇我們要加載的操作系統,即找到該操作系統的內核(kernel),從而啓動第一個進程init 進程,讀取/etc/inittab 配置文件(需自己來進行編寫),即init進程所要的表格,無論我們進入哪一個級別,都要執行/etc/rc.s/rc.sysinit 腳本的(這個是記錄鍵盤輸入設備輸入數據、網絡功能等,即進入的init 級別),若輸入的是‘3’則執行/etc/rc.d/rc腳本,執行/etc/rc3.d/*了.
系統開機的經過可
總的來說linux啓動的流程如下分析:
1. 加載 BIOS 的硬件信息與進行自我測試,並依據設定取得第一個可開機的裝置;
2. 讀取並執行第一個開機裝置內 MBR 的boot Loader (亦即是grub, spfdisk 等程序) ;
3. 依據 boot loader 的設定加載 Kernel ,Kernel 會開始偵測硬件不加載驅動程序;
4. 在硬件驅動成功後,Kernel 會主動呼叨 init 程序,而 init 會取得 run-level 信息;
5. init 執行/etc/rc.d/rc.sysinit 檔案來準備軟件執行的作業環境 (如網絡、時區等) ;
6. init 執行 run-level 的各個服務的啓動(script 方式) ;
7. init 執行/etc/rc.d/rc.local 檔案;
8. init 執行終端機仿真程序 mingetty 來啓動login 程序,最後就等待用戶登入啦;
開始打造自己的linux:
安裝在硬盤上,在硬盤上應具備內核,應用,怎樣把這些應用放在硬盤上吶?
找一個完好的宿主機,把宿主機上的內核和應用移植到硬盤上,然後把硬盤扣出來。
1.添加硬盤,在虛擬機添加一個20G左右新硬盤放在指定目錄下。
2.查看我們添加的硬盤名稱:fdisk -l 看到有/dev/sdb 這個就是我們插入新硬盤盤名。
現在開始創建並引導可以啓動的新硬盤:
嗯,這個新加的硬盤做好後會挪到別的機器上做sda盤,啓動盤,必須用自己的引導分區和根分區。必須建分區,
Fdisk /dev/sdb n p(增加主分區) 1 +100MB p (查看) n p 2 +1000MB
N P 3 +500M 分區就建好了,這是看一下sd3 id號爲83 ,sd3 是副分區得改一下其id號=82 , t 82 就可以了,w 。
執行一下:partprobe /dev/sdb 格式化這3個分區mkfs -t ext3 /dev/sdb1 mkfs -t ext3 /dev/sdb2 mkfs -t ext3 /dev/sdb3
查看一下分區:fdisk -l sdb1 作爲另一臺機器上的引導分區,sdb2 作爲根分區。
建立光盤過載點: mkdir /mnt/sysroot mkdir /mnt/boot
Mount /dev/sdb1 /mnt/boot/ mount /dev/sdb2 /mnt/sysroot/
一個硬盤首先要有它的mdir ,怎莫來構建類?那個程序分爲兩段一段在grub內部,一段在磁盤上, 構建這些東西用這個指令:
grub-install --root-directory=/mnt/(根分區掛載點/root/不用寫自動識別) /dev/sdb
查看一下grub目錄掛載上沒? ll /mnt/boot/ 再查看一下grub目錄的文件,缺少一個grub菜單文件,我們自己來建一個。先拷貝下宿主機的內核。
cp /boot/vmlinuz-2.6.18-164.el5 /mnt/boot/cp /boot/initrd-2.6.18-164.el5.img /mnt/boot/
創建一個工作用的文件夾,先把initrd-2.6.18-164.el5.img 拷貝到該文件夾中,因爲這是一個壓縮的鏡像文件,在該目錄裏好解壓,好管理
[root@localhost boot]# mkdir /tmp/abc
[root@localhost boot]# mv initrd-2.6.18-164.el5.img /tmp/abc 進入abc目錄
[root@localhost abc]# zcat initrd-2.6.18-164.el5.img | cpio -id (cpio -id 爲防止出現亂碼指令)
Zcat 是查看壓縮包的文件 ll 就可以看到所有文件了。
在這有必須執行的init文件,我們可以查看一下,vim init (下面摘錄幾行)
3 mount -t proc /proc /proc 掛載驅動程序指令
7 mount -t sysfs /sys /sys 也是掛載虛擬文件系統
mknod /dev/tty c 5 0 mknod 創建各種節點
87 #resume LABEL=SWAP-sda3 交換分區因爲sdb3分區沒有格式化,先禁用,不改會報錯
88 echo Creating root device.
89 mkrootdev -t ext3 -o defaults,ro sda2
再次查看該目錄,刪除initrd-2.6.18-164.el5.img
查看所有文件的目錄: find .
[root@localhost abc]# find . |cpio -o -H newc --quiet |gzip -9 >initrd.gz (--quite 採取靜:默模式 由於這個文件太大,壓縮一下-9值最大壓縮值>指向自己命名的壓縮包名稱 )
[root@localhost abc]# cp initrd.gz /mnt/boot/ 把這個目錄文件ccopy到根分區根目錄下,該文件加載各種驅動。
編輯缺少的grub菜單。
Cd /mnt/boot/grub/ vim grub.conf
讀取目錄 .!ls /mnt/boot/vmlinuz<tab> /mnt/boot/initrd.gz
1 default=0
2 timeout=5
3 hiddenmenu
4 title my linux
5 root(hd0,0)
6 initrd /initrd.gz
7 kernel /vmlinuz-2.6.18-164.el5 ro root=/dev/sda2 quiet
現在我們做到加載內核 ,接下來該做init進程目錄了。
移植init 進程,
Which init 查看宿主機boot/ 目錄下的所有目錄 ll / 命令
在新建硬盤/mnt/sysroot/ 這些目錄都還沒有,得建立。
[root@localhost sysroot]# mkdir dev etc home lib media misc mnt net opt proc root sbin selinux srv sys tftpboot tmp usr varbin
[root@localhost sysroot]# mkdir etc/rc.d
[root@localhost sysroot]# cp /sbin/init sbin/
查看目錄所依賴的庫。
[root@localhost sysroot]# ldd /sbin/init
linux-gate.so.1 => (0x0011e000)
libsepol.so.1 => /lib/libsepol.so.1 (0x00434000)
libselinux.so.1 => /lib/libselinux.so.1 (0x0041a000)
libc.so.6 => /lib/libc.so.6 (0x0026a000)
libdl.so.2 => /lib/libdl.so.2 (0x003db000)
/lib/ld-linux.so.2 (0x0024c000)
我們必須拷貝這些庫文件到lib目錄下,一般用腳本。
cp /lib/libsepol.so.1 lib/
[root@localhost sysroot]# cp /lib/libselinux.so.1 lib/
[root@localhost sysroot]# cp /lib/libselinux.so.1 lib/
cp: overwrite `lib/libselinux.so.1'? n
[root@localhost sysroot]# cp /lib/libc.so.6 lib/
[root@localhost sysroot]# cp /lib/libdl.so.2 lib/
[root@localhost sysroot]# cp /lib/ld-linux.so.2 lib/
需要一個inittable 表格放在etc目錄下
先看一看原來了宿主機內的inittable 表格:
Vim /etc/inittable
18 id:5:initdefault: 默認的運行級別爲5
21 si::sysinit:/etc/rc.d/rc.sysinit 無論進入哪一個級別我們都要執行這個命令, 我們只需拷貝這一句話到inittable 表格中就可以了。
只需在該文件夾裏執行這個命令::21 w /mnt/sysroot/etc/inittable w是寫入到...:
si::sysinit:/etc/rc.d/rc.sysinit (si是指系統初始化標誌,:: 空白表示在任何一種級別,sysinit 表示他的動作,/etc/rc.d/rc.sysinit 表示我要運行的腳本)
這是我們查看一下該硬盤的/etc.rc.d/rc.sysinit 文件是否存在?
[root@localhost rc.d]# ll
total 0
可見並不存在,先查看一下宿主機上的該目錄內容:
[root@localhost rc.d]# file /etc/rc.d/rc.sysinit
/etc/rc.d/rc.sysinit: Bourne-Again shell script text executable 這是一個bash可執行的腳本。
現在我們自己做個比較簡單的:內容如下:
#!/bin/bash
echo -e "\033[31m dabinLINUX \033[0m"
/bin/bash
這個腳本是可執行的,賦予它一個權限:
[root@localhost rc.d]# chmod a+x rc.sysinit
現在看一下我們走到哪裏了?從那個啓動示意圖上可以看到:都做差不多了,那摩得有bash文件來啓動腳本文件,所以把宿主機上的bash文件拷貝到該硬盤的/mnt/sysroot/bin 目錄下,
[root@localhost rc.d]# which bash
/bin/bash
[root@localhost rc.d]# cp /bin/bash /mnt/sysroot/bin
這時候又該做一個連接庫了,也就是cp 文件到 lib/目錄下
[root@localhost sysroot]# cp /lib/libtermcap.so.2 lib/
[root@localhost sysroot]# cp /lib/libdl.so.2 lib/
cp: overwrite `lib/libdl.so.2'? y
[root@localhost sysroot]# cp /lib/libc.so.6 lib/
cp: overwrite `lib/libc.so.6'? y
[root@localhost sysroot]# cp /lib/ld-linux.so.2 lib/
cp: overwrite `lib/ld-linux.so.2'? Y
可見我們已經有些都拷貝過了,我們只需覆蓋。
查看一下:
[root@localhost lib]# tree
.
|-- ld-linux.so.2
|-- libc.so.6
|-- libdl.so.2
|-- libselinux.so.1
|-- libsepol.so.1
`-- libtermcap.so.2
現在都基本上這個空殼linux做完了,現在可以試着執行以下看看。
在此多次輸入sync命令,使我們在硬盤上做的各種動作,都完全寫到此硬盤上。
[root@localhost ~]# sync
[root@localhost ~]# sync
1>先把宿主機停下來,打開新的機器,把原來的硬盤拆除,掛接一個新的硬盤,
2>打開該虛擬機就可以啓動了。
這樣就行了啦。
下面我們再來移ls 、init、等命令,可以這樣搞。(其實就是一些鏈接庫的cp拷貝到lib目錄下)
Ls :命令:
[root@localhost sysroot]# which ls
alias ls='ls --color=tty'
/bin/ls
[root@localhost sysroot]# cp /bin/ls bin/
[root@localhost sysroot]# ldd /bin/ls
linux-gate.so.1 => (0x00122000)
librt.so.1 => /lib/librt.so.1 (0x009e6000)
libacl.so.1 => /lib/libacl.so.1 (0x00660000)
libselinux.so.1 => /lib/libselinux.so.1 (0x0083f000)
libc.so.6 => /lib/libc.so.6 (0x00123000)
libpthread.so.0 => /lib/libpthread.so.0 (0x0053a000)
/lib/ld-linux.so.2 (0x006a2000)
libattr.so.1 => /lib/libattr.so.1 (0x0093f000)
libdl.so.2 => /lib/libdl.so.2 (0x00b37000)
libsepol.so.1 => /lib/libsepol.so.1 (0x00337000)
[root@localhost sysroot]# sync
[root@localhost sysroot]# sync
這樣在自己的linux系統下就可以使用ls命令了。
接下來是init命令的植入
先來了解一下init 的。
進入0級別,也就是關機級別:
[root@localhost ~]# cd /etc/rc.d/rc0.d 進入這個目錄。
這個目錄下有許多文件進程,也就是隻要我們進入0級別,都要把這麼多進程殺掉,
也要啓用一個進程?:lrwxrwxrwx 1 root root 17 Aug 7 05:05 S00killall -> ../init.d/killall
lrwxrwxrwx 1 root root 14 Aug 7 05:05 S01halt -> ../init.d/halt
[root@localhost rc0.d]# vim S01halt 進入這個文件看一下。
查看最後一行:222 exec $command $HALTARGS 用$執行 command、 HALTARGS 都是一個變量。可以查看一下commond 在此文件裏做什麼用處。
220 [ "$INIT_HALT" != "HALT" ] && HALTARGS="$HALTARGS -p" 這一行設置了參數 -p
則222行的聲明是執行HALTARGS -p 的關機指令,
接下來查看宿主機的inittab文件。
[root@localhost etc]# vim /etc/inittab
末行模式執行:23 w>>/mnt/sysroot/etc/inittab 把23行的0級別內容移植到新硬盤的inittab目錄下。
進入新硬盤/mnt/sysroot/etc/inittab 文件進行編譯。
內容如下:(爲了方便我自己取了個文件名字:rc.sysdown)
si::sysinit:/etc/rc.d/rc.sysinit
l0:0:wait:/etc/rc.d/rc.sysdown
改寫好這個文件後我們得創建rc.sysdown shell 腳本。
[root@localhost rc0.d]# cd /mnt/sysroot/etc/rc.
[root@localhost rc.d]# vim rc.sysdown
[root@localhost rc.d]# chmod a+x rc.sysdown
上面的shell文件的執行文件還沒有,我們把它copy到/mnt/sysroot/sbin/目錄下。
[root@localhost rc.d]# cp /sbin/halt /mnt/sysroot/sbin
這是就可以執行0級別關機了。
接下來設置主機名:
恩,這個開始時我們提過了,執/etc/rc.s/rc.sysinit 腳本的(這個是記錄鍵盤輸入設備輸入數據、網絡功能等,即進入的init 級別)現在看一下這個文件宿主機怎麼編譯的哦
[root@localhost ~]# vim /etc/rc.d/rc.sysinit
在接下來查看/etc/sysconfig/network 文件
這時,我們分析完了,來在新硬盤裏建立編寫這個文件
[root@localhost ~]# vim /mnt/sysroot/etc/rc.d/rc.sysinit
[root@localhost ~]# mkdir /mnt/sysroot/etc/sysconfig
[root@localhost ~]# cd /mnt/sysroot/etc/sysconfig
[root@localhost sysconfig]# vim network
進入末行模式:
:r /etc/sysconfig/network copy到該文件裏。
這時想到我們這裏得修改一下:
[root@localhost ~]# vim /mnt/sysroot/etc/rc.d/rc.sysinit
這時還沒有copy 宿主機下的/mnt/hostname指令
[root@localhost sysconfig]# cp /bin/hostname /mnt/sysroot/bin/
接下來該拷貝鏈接庫文件:
[root@localhost bin]# ldd hostname
拷貝完鏈接庫後
[root@localhost ~]# sync
[root@localhost ~]# sync
就可以執行hostname指令了。
可以說想要神馬功能就可以構建這項功能。歡迎來訪,有什麼疑問我們共同探討。