CentOS5、6的啟動流程
? ? Linux:kernel + rootfs,Linux系統就是內核加上根文件系統。
內核之上是庫:
庫:函數集合,function,函數具有調用接口,庫函數不能單獨執行,必須被其他程序調用
? ? 過程調用:procedure,沒有返回結果
? ? 函數調用:function,有返回結果
程序:程序調用庫或系統調用,完成業務,可以單獨執行。
內核設計流派:
? ? 單內核模式:Linux,把所有功能集成于同一個程序
? ? 微內核模式:Windows,Solaris,每種功能使用一個單獨子系統實現
Linux內核特點:
? ? 支持模塊化:.ko(是內核的模塊,相對的有.so,共享對象模塊,是共享庫的模塊文件)
? ? 支持模塊的動態裝載和卸載;
? ? 組成部分:
? ? ? ? 核心文件:/boot/vmlinuz-VERSION-release
? ? ? ? ? ? ramdisk:
? ? ? ? ? ? ? ? CentOS 5:/boot/initrd-VERSION-release.img
? ? ? ? ? ? ? ? CentOS 6:/boot/initramfs-VERSION-release.img
? ? ? ? 模塊文件:/lib/modules/VERSION-release
ramdisk是用文件來模擬磁盤,提供最開始的根文件系統,以裝載系統啟動必須的驅動。? ? ? ??
CentOS 系統啟動流程:
? ? POST:加電自檢
? ? ? ? ROM:CMOS,BIOS:Basic Input and Output System
? ? ? ? 內存是ROM+RAM組成
? ? BOOT sequence:按次序查找各引導設備,第一個有引導程序的設備即為本次啟動用到的設備
? ? ? ? bootloader:引導加載器,程序
? ? ? ? ? ? windows:ntloader
? ? ? ? ? ? Linux:LILO——LInux LOader;GRUB——GRand Uniform Bootloader,GRUB有0.X版,叫做GRUB Legacy,GRUB 1.X,叫GRUB2
? ? ? ? bootloader功能:提供一個菜單,允許用戶選擇要啟動系統或不同的內核版本;把用戶選定的內核裝載到內存中的特定空間中,解壓、展開,并把系統控制權移交給內核;
? ? MBR:(0磁道0扇區)
????????446:bootloader
? ? ? ? 64:fat
? ? ? ? 2:55AA
? ? GRUB:
? ? ? ? bootloader:1st stage
? ? ? ? disk:2nd stage
kernel:
? ? 自身初始化:
? ? ? ? 探測可識別到的所有硬件設備;
? ? ? ? 加載硬件驅動程序;(有可能會借助于ramdisk加載驅動)
? ? ? ? 以只讀方式掛載根文件系統;
? ? ? ? 運行用戶空間的第一個應用程序:/sbin/init
? ? init程序的類型:
? ? ? ? SysV:init,CentOS 5
? ? ? ? ? ? 配置文件:/etc/inittab
? ? ? ? Upstart:init,CentOS 6
? ? ? ? ? ? 配置文件:/etc/inittab, /etc/init/*.conf
? ? ? ? Systemd:systemd,CentOS 7
? ? ? ? ? ? 配置文件:/usr/lib/systemd/system, /etc/systemd/system
? ? ramdisk:
? ? ? ? 內核中的特性之一:使用緩沖和緩存來加速對磁盤上的文件的訪問
? ? ? ? ramdisk --> ramfs,CentOS5將ramdisk模擬成磁盤,導致內核再次緩沖
? ? ? ? CentOS5:initrd,工具程序:mkinitrd
? ? ? ? CentOS6:initramfs,工具程序:mkinitrd,dracut
系統初始化:
? ? POST --> BootSequence(BIOS)?--> Bootloader(MBR)?--> kernel(ramdisk)?--> rootfs(只讀)?--> init
/sbin/init
? ? CentOS 5:
? ? 運行級別:為了系統的運行或維護等應用目的而設定,共0-6,一個7個級別
? ? ? ? 0 :關機
? ? ? ? 1 :單用戶模式(root,無須登錄),single,維護模式;
? ? ? ? 2 :多用戶模式,會啟動網絡功能,但不會啟動NFS,維護模式;
? ? ? ? 3 :多用戶模式,正常模式,文本界面
? ? ? ? 4 :預留級別,可同3級別
? ? ? ? 5 :多用戶模式,正常模式,圖形界面
? ? ? ? 默認級別:3,5
? ? ? ? 切換級別:init #
? ? ? ? 查看級別:runlevel、who -r
各級別的不同之處,主要在于init按照配置文件進行的初始化的不同
配置文件:/etc/inittab? ?(CentOS 5)
每行定義一種action以及與之對應的process
? ? id : runlevel : action : process
? ? action:
? ? ? ? wait:切換至此級別運行一次
? ? ? ? respawn:此process終止,就重新啟動之
? ? ? ? initdefault:設定默認運行級別,process省略
? ? ? ? sysinit:設定系統初始化方式,此處一般指定為/etc/rc.d/rc.sysinit
示例:? ?
? ? id : 3 : initdefault :?
? ? si :? : sysinit : /etc/rc.d/rc.sysinit
? ? l0 : 0 : wait : /etc/rc.d/rc 0
? ??l1 : 1 : wait : /etc/rc.d/rc 1
? ? ........
? ? l6 : 6 : wait : /etc/rc.d/rc 6
? ? 說明:rc 0-->意味著讀取/etc/rc.d/rc0.d/目錄下的文件(腳本鏈接),文件以K或S開頭
? ? ? ? K*:K##*,##運行次序,越小越先運行,K是Kill要關閉的,數字越小的服務,通常為依賴到別的服務。
? ? ? ? S*:S##*,S是Start,要啟動的,數字越小越先運行,數字小的服務,通常為被依賴到的服務。
? ? ? ? for srv in /etc/rc.d/rc0.d/K*;do
? ? ? ? ? ? $srv stop
? ? ? ? done
? ? ? ? for srv in /etc/rc.d/rc0.d/S*;do
? ? ? ? ? ? $srv start
? ? ? ? done
?
chkconfig命令:查看每個服務在不同級別下是啟動還是關閉的。
chkconfig --list
? ? chkconfig --level 3 NetworkManager? off? ?修改級別下是啟動還是關閉,即修改K或S
添加:
? ? SysV的服務腳本放置于/etc/rc.d/init.d (/etc/init.d)
? ? ? ? chkconfig --add name
測試添加自定義的服務:testsrv:
1)在/etc/rc.d/init.d目錄下新建testsrv文件
2)給testsrv文件增加執行權限:
chmod +x testsrv
3)加到服務中去:
chkconfig --add testsrv
下圖是添加服務前的文件
添加后,查看結果:
刪除:
? ? chkconfig --del?name
? ? chkconfig --del testsrv
修改指定的鏈接類型
? ? chkconfig [--level levels] name <on | off | reset>
? ? ? ? --level ####:指定要設置的級別;省略時表示2345
特殊的S99local服務:正常級別下,最后啟動的一個服務,沒有連接至/etc/rc.d/init.d目錄下
指向的是上級目錄的rc.local,是一個腳本文件,可以將不便或不需要寫為服務腳本放于/etc/rc.d/init.d目錄下,不需要chkconfig管理,但又想開機時自動運行的命令或腳本寫入此文件。
/etc/rc.local也指向/etc/rc.d/rc.local
在init的最后,就是要啟動一個供用戶登錄的會話窗口,使用戶可以登錄,登錄后,啟動bash進行交互操作。假設這個登錄在inittab中如下:
tty1:2345:respawn:/usr/sbin/mingetty tty1
tty2:2345:respawn:/usr/sbin/mingetty tty2
......
tty6:2345:respawn:/usr/sbin/mingetty tty6
? ? mingetty會調用login程序,以驗證用戶登錄合法性
/etc/rc.d/rc.sysinit:系統初始化腳本,完成以下功能
? ? (1)設置主機名
? ? (2)設置歡迎信息
? ? (3)激活udev和selinux
? ? (4)掛載/etc/fstab文件中定義的文件系統
? ? (5)檢測根文件系統,并以讀寫方式重新掛載根文件系統
? ? (6)設置系統時鐘
? ? (7)激活swap設備
? ? (8)根據/etc/sysctl.conf文件設置內核參數
? ? (9)激活lvm及software raid設備
? ? (10)加載額外設備的驅動程序
? ? (11)清理操作
總結:(CentOS 5的init)
/sbin/init --> (/etc/inittab) --> 設置默認運行級別 --> 運行系統初始化腳本、完成系統初始化 -->關閉對應級別下需要關閉的服務,啟動需要啟動的服務 --> 設置登錄終端
CentOS 6:
? ? init程序為:upstart,由Ubuntu研制,其配置文件:/etc/inittab 、/etc/init/*.conf,主要是后者,即將CentOS5的inittab分割成多個.conf文件。
注意:/etc/init/*.conf文件語法,遵循upstart配置文件語法格式;
網上找的啟動流程圖:
CentOS5、6忘記密碼的解決:
? ? 啟動系統時,設置其運行級別1:啟動時,提示按任意鍵進入隱藏的GRUB菜單
? ??
按e鍵可以編輯菜單:
root (hd0,0)指定grub根目錄所在設備位置,這里是第一個硬盤的第一個分區,這里root是grub的命令,指定boot所在的分區作為grub的根目錄
kernel是加載內核,指定內核文件,以只讀(ro)加載文件系統的根目錄,即根分區,root=。。。參數指定文件系統根分區的位置,使用了lvm
initrd是將.img文件作為虛擬磁盤載入內存,模擬根文件系統,其上有少量驅動程序等,如要使用lvm,必須加載lvm文件系統驅動
以上指定的分區、設備可以參考下面查看到的信息
通過上面的信息,root(hd0,0)就是指定/boot所在的分區,即/dev/sda1,kernel加載的內核文件 /vmlinuz-2.6.32-754.el6.x86_64,實際上是(hd0,0)/vmlinuz-2.6.32-754.el6.x86_64,這里的根是指的boot分區,后面的參數root=/dev/mapper/vg_study610-lv_root,才是指定文件系統的根分區,其使用的是lvm,看上圖,mount信息中根“/”的掛載設備就是這里的參數值。initrd是在沒有加載文件系統根目錄前,模擬的根文件系統,以提供部分驅動。如要想使用真正的根文件系統,必須加載lvm驅動,這個就要放在initrd的文件中。
這里編輯kernel這一行,這個命令行很長,具體如下:
kernel /vmlinuz-2.6.32-754.el6.x86_64 ro root=/dev/mapper/vg_study610-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD rd_LVM_LV=vg_study610/lv_swap SYSFONT=latarcyrheb-sun16 crashkernel=auto rd_LVM_LV=vg_study610/lv_root ?KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
在其后添加空格 1或single,表示運行于level 1級別。然后回車,確認修改,回到上一級菜單,然后按b鍵,表示啟動運行這個內核。
不需要輸入密碼,直接以root登錄了,然后可以修改密碼。
GRUB(Boot Loader):
grub legacy(grub1)
? ? stage 1:mbr
? ? stage1_5:mbr之后的扇區,讓stage1中的bootloader能識別stage2所在的分區上的文件系統
? ? stage2:磁盤分區(/boot/grub/)
? ? 配置文件:/boot/grub/grub.conf? <-- /etc/grub.conf
? ? stage2及內核等通常放置于一個基本磁盤分區;
? ? 功用:
? ? ? ? (1)提供菜單,并提供交互式接口
? ? ? ? ? ? e:編輯模式,用于編輯菜單
? ? ? ? ? ? c:命令模式,交互式接口
? ? ? ? (2)加載用戶選擇的內核或操作系統
? ? ? ? ? ? 允許傳遞參數給內核|
? ? ? ? ? ? 可隱藏此菜單
? ? ? ? (3)位菜單提供了保護機制
? ? ? ? ? ? 為編輯菜單進行認證
? ? ? ? ? ? 為啟用內核或操作系統進行認證
如何識別設備:
? ? (hd#,#):第一個#表示磁盤號,第二個#表示第#個分區,都是從0開始編號。
grub的命令行接口:
? ? find (hd#,#)/PATH/TO/SOMEFILE:查找特定文件
? ? root (hd#,#):指定根目錄
? ? kernel /PATH/TO/KERNEL_FILE:設定本次啟動時用到的內核文件;額外還可以添加許多內核支持使用的cmdline參數,如:
? ? ? ? init=/path/to/init?, selinux=0
? ? initrd?l /PATH/TO/INITRAMFS_FILE:設定為選定的內核提供額外文件的ramdisk
? ? boot:引導啟動選定的內核? ??
手動在grub命令行接口啟動系統:
? ? grub>root (hd0,0)
? ? grub>kernel /vmlinuz-VERSION-RELEASE ro root=/dev/DEVICE
? ? grub>initrd /initramfs-VERSION-RELEASE.img
? ? grub>boot
grub配置文件:/boot/grub/grub.conf
? ? 配置項:
? ? ? ? default=#:設定默認啟動的菜單項;菜單項(title)標號從0開始
? ? ? ? timeout=#:指定菜單項等待選項選擇的時長
? ? ? ? splashimage=(hd#,#)/PATH/TO/XPM_PIC_FILE:指明菜單項背景圖片文件路徑
? ? ? ? hiddenmenu:隱藏菜單
? ? ? ? password [--md5] STRING:菜單編輯認證
? ? ? ? title TITLE:定義菜單項“標題”,可出現多次,引導不同的內核
? ? ? ? ? ? root (hd#,#):grub查找stage2及kernel文件所在設備分區:為grub的“根”
? ? ? ? ? ? kernel /PATH/TO/VMLINUZ_FILE [PARAMETERS] :啟動的內核
? ? ? ? ? ? initrd /PATH?TO?INITRAMFS_FILE:內核匹配的ramfs文件
? ? ? ? ? ? password [--md5] STRING:啟動選定的內核或操作系統時進行認證
grub-md5-crypt:grub提供的加密工具
安裝grub:grub-install命令
? ? (1)grub-install
? ? ? ? grub-install --root-directory=ROOT /dev/DISK
? ? (2)grub
? ? ? ? grub>root (hd#,#)
? ? ? ? grub set (hd#)
實驗1:新增加一塊硬盤,在此硬盤上安裝grub并設置init為bash。(即為新盤安裝系統)
? ? (1)新增一塊硬盤
? ? ? ? (2)對新增的磁盤做分區
使用fdisk /dev/sdb進行分區
sdb1為boot分區,sdb2為swap分區,sdb3為根分區。
? ? (3)安裝文件系統:
? ? (4)將sdb1掛載到當前系統中,sdb1作為新系統的boot分區
? ? (5)安裝grub
運行grub-install:
? ? grub-install --root-directory=/mnt /dev/sdb
這里需要注意的是--root-directory的指定,這里是指定boot的根,實驗的boot分區是掛載在/mnt/boot下,所以/mnt/boot應該為boot的根,但是grub安裝程序會自動在根下創建boot子目錄,所以,如果--root-directory指定為/mnt/boot的話,最終會創建/mnt/boot/boot/grub,所以根目錄指定不包括boot子目錄。如下的測試:
在grub目錄下,可以看到stage1,stage1_5和stage2,stage1此時已經安裝到了sdb磁盤的MBR,grub中缺少配置文件,手動創建一個。
同時,在boot的根目錄下,此時還沒有內核文件與ramfs文件,拷貝當前系統的文件到此目錄下:
這里要注意的是:第一條 root (hd0,0)為何是(hd0,0),因為最終這塊磁盤要單獨作為系統使用,這就成為了第一磁盤,第二條kernel中的root,是最終單獨使用磁盤時,作為根目錄的磁盤,即前面分區的sdb3,最終成為sda3。
然后,要成為文件系統的根,需要按照FHS,創建相應的目錄結構:
拷貝bash程序到對應目錄,作為新系統啟動后運行的進程,一個程序要運行,不但要拷貝程序本身,還要有對用的共享庫,測試拷貝的bash是否可用,可以將根切換到新系統:chroot /mnt/sysroot
修改一下grub.conf配置文件,將kernel命令添加參數init=/bin/bash,即限定kernel后的init是bash,而不是默認的init。
? ? (6)新建虛擬機,其硬盤使用剛才的磁盤。
? ? (7),啟動新建的虛擬機
啟動失敗,原因是拷貝的內核中啟動了selinux,在配置菜單中添加禁止selinux的參數:
系統引導成功。
實驗2:本機grub損壞,但是系統還在運行中。
? ? (1)備份MBR,然后破壞MBR,但不破壞分區表,即MBR中的前446被破壞:
此時,重啟系統就會出錯。
? ? (2)使用grub-install修復:
如此,便修復了MBR。
? ? (3)還可以進入grub命令交互界面:
指定boot根:root (hd0,0)
修復: setup (hd0)
可以看到,setup檢測到stage1不存在了,然后安裝執行了stage1,在MBR,然后在隨后的27個扇區安裝的stage1_5。
如此,也修復完畢。
實驗3:本機grub損壞,重啟系統了,此時需要使用使用修復模式(Rescue)進行修復,需要另外的啟動盤,如光盤、U盤等。
破壞MBR:
重新啟動后:
鏈接ISO文件,從光驅啟動:
最后一項回車:
選擇Rescue a CentOS system,或者在第一個界面按Esc,進入命令行,鍵入:linux rescue
可以看到,已經發現了已安裝的系統,并將其掛載到/mnt/sysimage下。
按回車,運行shell,在shell下,切換root到原來的系統
再次啟動,可以引導。
CentOS6的界面:
以上方法恢復后,重新啟動引導后出現如下警告:
等待重新加載后,啟動成功。
Linux Kernel:
? ? 單內核模式、但充分借鑒了微內核模式的優先,為內核引入模塊化機制。
? ? 內核組成部分:
? ? ? ? kernel:內核核心,一般為bzImage,通常在/boot目錄下,名稱為vmlinuz-VERSION-RELEASE
? ? ? ? kernel object:內核對象,一般放置于/lib/moudles/VERSION-RELEASE/目錄下
? ? ? ? 內核對象可以做成模塊功能的,有三種選擇:
? ? ? ? ? ? [ ]:N ,不選擇,不編譯此功能
? ? ? ? ? ? [M]:M,選擇編譯成模塊
? ? ? ? ? ? [*] :Y,編譯成內核核心部分。
? ? ? ? 輔助文件:ramdisk,兩種
? ? ? ? ? ? initrd 和?initramfs
運行中的內核:uname命令
? ? uname [option]...
? ? ? ? -n:顯示節點名稱
? ? ? ? -r:顯示VERSION-RELEASE號
? ? lsmod :查看已經裝載的內核模塊,此命令讀取的是/proc/modules文件的內容。
查看某模塊詳細信息:modinfo [option] 模塊名
參數:-n、-p、-a、-d、-l
裝載或卸載模塊命令:modprobe?
裝載:modprobe [-C config-file] [moudlename] [module parameters...]
? ? 配置文件:/etc/modprobe.conf,/etc/modprobe.d/*.conf
卸載:modprobe [-r] modulename...
查詢模塊信息時,能夠看到依賴關系,這個依賴關系是保存在/lib/modules/VERSION-RELEASE/modules.dep文件中,實際使用是將其編譯成二進制,即modules.dep.bin文件。
depmod命令:內核模塊依賴關系文件及系統信息映射文件的生成工具。
裝載或卸載內核模塊的其他命令:
? ? insmod [filename] [module option]
? ? rmmod modulename
/proc目錄:
? ? 內核把自己內部狀態信息及統計信息,以及可配置參數通過proc偽文件系統加以輸出。
? ? 參數:
? ? ? ? 只讀:輸出信息
? ? ? ? 可寫:可接受用戶指定“新值”來實現對內核某功能或特性的配置,主要在?/proc/sys目錄
? ? ? ? sysctl命令用于查看或設定此目錄中諸多參數
? ? ? ? ? ? sysctl -w path.to.parameter=VALUE
? ? ? ? echo命令通過重定向的方式也可以修改大多數參數的值;
? ? ? ? ? ? echo "VALUE" > path/to/parameter
sysctl命令,配置文件為/etc/sysctl.conf
? ? (1)設置某參數: sysctl -w path.to.parameter=VALUE
? ? (2)通過讀取配置文件設置參數:sysctl -p [/path/to/conf_file]
內核中的路由轉發:是否開啟功能是配置在如下位置的:
? ? /proc/sys/net/ipv4/ip_forward
默認為0,沒有開啟路由轉發功能
想修改為永久有效,可以編輯/etc/sysctl.conf:
將net.ipv4.ip_forward=0改為=1
修改后不會立即生效,需要重讀配置文件
常用的幾個參數:
? ? net.ipv4.ip_forward? ?:路由轉發
? ? vm.drop_caches? ? :回收緩存
? ? kernel.hostname? ? :主機名
/sys目錄:
? ? sysfs:輸出內核識別出的各硬件設備的相關屬性信息,也有內核對硬件特性的設定信息;有些參數是可以修改的,用于調整硬件的工作特性。
udev通過此路徑下輸出的信息動態為各設備創建所需要設備文件;udev是運行在用戶空間程序;專用工具:udevadmin、hotplug
udev為設備創建設備文件時,會讀取其事先定義好的規則文件,一般在/etc/udev/rules.d及/lib/udev/rules.d目錄下。
ramdisk文件的制作:
? ? mkinitrd [OPTION...] [<initrd-image>] <kernel-version>
? ? ? ? mkinitrd /boot/initramfs-$(uname -r).img? $(uname -r)
? ??dracut [OPTION]... <image> ?<kernel-version>
????????dracut /boot/initramfs-$(uname -r).img? $(uname -r)
ramdisk文件是一個gz壓縮文件,修改后綴名后,解壓縮,再看文件類型,是cpio歸檔文件,將其展開,基本上是簡化的根系統。sbin/目錄下有switch_root,就是內核完成啟動后最后的根切換要執行的程序。
編譯內核:
? ? 前提:
? ? ? ? (1)準備好開發環境;
? ? ? ? (2)獲取目標主機上硬件設備的相關信息;
? ? ? ? (3)獲取到目標主機系統功能的相關信息,例如要啟用的文件系統;
? ? 開發環境:
? ? ? ? Development Tools和Server Platform Development兩個包組
? ? 目標主機硬件設備相關信息:
? ? ? ? CPU:cat /proc/cupinfo 或lscpu 或x86info -a (這個需要安裝yum install x86info)
? ? ? ? PCI設備:lspci -v 或 lsusb -v或lsblk?
? ? 了解全部硬件設備信息,hal-device
? ? 編譯時可以使用現有配置文件模板,在/boot目錄下有當前運行系統編譯時的配置文件,可以作為新系統編譯時的配置模板:/boot/config-2.6.32-754.el6.x86_64
? ? 開始:
? ? ? ? (1)下載新版本內核源碼:如linux-3.10.67.tar.gz ??
? ? ? ? (2)解壓到/usr/src下:tar xf?linux-3.10.67.tar.gz -C /usr/src
? ? ? ? (3)做一個鏈接:理ln -sv?linux-3.10.67.tar.gz linux
? ? ? ? (4)拷貝/boot/config-2.6.32-754.el6.x86_64到/usr/src/linux/下,命名為.config
? ? ? ? (5)make menuconfig,對新編譯的版本進行配置
? ? ? ? (6)開始編譯,make ,還可以啟動多線程make -j 4
? ? ? ? 因為make是終端相關的,如果一不小心關閉了終端,結果就悲劇了,所以可以使用screen,打開虛擬屏幕
使用Ctrl+ad退出。
執行make -j 4開始編譯。此時終端斷開,進入后編譯依然存在。
screen -ls查看存在的虛擬屏幕,使用screen -r 編號 重新進入
? ? ? ? (7)make modules_install
? ? ? ? (8)make install
? ? ? ? ? 安裝bzImage為/boot/vmlinuz-VERSION-RELEASE
? ? ? ? ? 生成initramfs文件
? ? ? ? ? 編輯grub配置文件
? ? ? ? (9)重啟系統,并測試新內核