開機——很多人覺得很簡單的事情,只要按下電源開關,然后系統就會自然啟動,沒有什么需要學習的。其實不然,如果系統沒有什么問題,可以正常登陸的時候,當然開機很簡單。但更多的時候,我們需要知道當機子不能正常開機的如何解決,這才是我們學習的目的。
那么我們就來分析一下Linux的開機流程
簡單來說,系統開機的過程可以匯整成下面的流程:
1.加載BIOS的硬件信息、進行自我測試,并依據設定獲得第一個可開機的設備;
2.讀取并執行第一個開機設備內MBR的boot Loader(grub等程序);
3.依據boot loader的設置加載Kernel,Kernel會開始檢測硬件與加載驅動程序;
4.內核啟動init
5.系統初始化:(/etc/init/rcS.conf exec /etc/rc.d/rc.sysinit)
6.init找到/etc/inittab文件,確定默認的運行級別(X) (/etc/init/rcS.conf exec telinit $runlevel)
7.觸發相應的runlevel事件(/etc/init/rc.conf exec /etc/rc.d/rc $RUNLEVEL)
8.開始運行/etc/rc.d/rc,傳入參數X
9./etc/rc.d/rc腳本進行一系列設置,最后運行相應的/etc/rcX.d/中的腳本
10./etc/rcX.d/中的腳本按事先設定的優先級依次啟動
11.最后執行/etc/rc.d/rc.local
12.加載終端或X-Window接口
?
BIOS, boot loader與kernel加載
BIOS, 開機自檢與MBR
在個人計算機架構下,你想要啟動整部系統首先就得要讓系統去加載BIOS(Basic Input Output System),并通過BIOS程序去加載CMOS的信息,并且藉由CMOS內的設定值取得主機的各項硬件配置信息(如CPU與接口設備的溝通頻率、開機設備的搜尋順序、硬盤的大小與類型、 系統時間、各周邊總線的是否啟動Plug and Play (PnP, 即插即用設備)、 各接口設備的I/O地址、以及與CPU溝通的IRQ(Interrupt ReQuest)中斷等等)。
在取得這些信息后,BIOS還會進行開機自檢(Power-on Self Test, POST)。 然后開始執行硬件檢測的初始化,并設定PnP設備,之后再定義出可開機的設備順序, 接下來就會開始進行開機設備的數據讀取了(MBR相關的任務開始)。
由于不同的操作系統的文件系統格式不相同,因此我們必須要以一個開機管理程序來處理內核文件的加載問題,因此這個開機管理程序就被稱為Boot Loader。這個Boot Loader程序安裝在開機設備的第一個扇區(sector)內,也就是我們一直談到的 MBR (Master Boot Record,主要啟動記錄區)。下圖就是MBR的組成圖
Boot Loader 的功能
Boot Loader最主要功能是認識操作系統的文件格式并加載內核到主存儲器中去執行。 由于不同操作系統的文件格式不一致,因此每種操作系統都有自己的boot loader,用自己的loader才有辦法載入內核文件。
問題就來了:如果在一部主機上面安裝多種不同的操作系統。 既然必須要使用自己的 loader才能夠加載屬于自己的操作系統內核,而系統的MBR只有一個,那怎么會有辦法同時在一部主機上面安裝多系統呢?下面就來看看如何實現的。
每個文件系統(filesystem, 或者是 partition) 都會保留一塊啟動扇區 (boot sector) 提供操作系統安裝 boot loader,而通常操作系統默認都會安裝一份 loader 到他根目錄所在的文件系統的boot sector 上。如果我們在一部主機上面安裝 Windows 與 Linux 后,該 boot sector, boot loader 與 MBR 的相關性會有點像下圖:
如上圖所示,每個操作系統默認是會安裝一套 boot loader 到他自己的文件系統中 (就是每個filesystem左下角的方框),而在Linux 統安裝時,你可以選擇將 boot loader 安裝到MBR中,也可以選擇不安裝。如果選擇安裝到MBR的話,那理論上在 MBR與boot sector都會保有一份boot loader程序。至于Windows安裝時,他預設會主動的將MBR與boot sector都裝上一份 boot loader。所以,你會發現安裝多操作系統時,你的MBR常常會被不同的操作系統的 boot loader所覆蓋。
現在還是沒有解決我們上面的問題。雖然各個操作系統都可以安裝一份 boot loader 到他們的boot sector中,這樣操作系統可以通過自己的boot loader 來加載內核了。問題是系統的MBR只有一個,要怎么執行 boot sector里面的 loader呢?
下面就來看看boot loader主要的功能
提供選項:用戶可以選擇不同的開機項目,這是多重引導的重要功能。
載入內核文件:直接指向可開機的程序區段來開始操作系統;
轉交其他loader:將開機管理功能轉交給其他loader負責。
由于具有選項功能,因此我們可以選擇不同的內核來開機。而由于具有控制權轉交的功能,因此我們可以加載其他 boot sector內的loader。不過 Windows的loader 預設不具有控制權轉交的功能,因此你不能使用 Windows 的 loader 來加載 Linux 的 loader。這也是特別強調先裝Windows再裝Linux的緣故。
如上圖所示,MBR使用Linux的grub 這個開機管理程序,并且里面已經有了三個選項,第一個選項可以直接指向Linux 的內核文件并且直接加載內核來開機;第二個選項可以將開機管理程控權交給 Windows 來管理,此時 Windows 的 loader 會接管開機流程,這個時候他就能夠啟動 windows 了。第三個選項則是使用 Linux 在 boot sector 內的開機管理程序,此時就會跳出另一個grub的選項。
重點就是要知道“boot loader的功能就是加載kernel文件”
加載內核檢測硬件與initrd的功能
由boot loader的管理而開始讀取內核文件后,接下來,Linux 就會將內核解壓縮到主存儲器當中, 并且利用內核的功能,開始測試與驅動各個周邊設備,包括儲存設備、CPU、網卡、聲卡等等。 此時 Linux 內核會以自己的功能重新檢測一次硬件,而不一定會使用 BIOS 檢測到的硬件信息。也就是說,內核此時才開始接管 BIOS 后的工作。 內核檔案一般來說,他會被放置到 /boot 里面,并且取名為 /boot/vmlinuz。
[root@yufei ~]# ls --format=single-column? /boot
config-2.6.32-71.el6.i686??????? <===系統kernel的配置文件,內核編譯完成后保存的就是這個配置文件
efi??????????????????????????????? <===Extensible Firmware Interface(EFI,可擴展固件接口)是 Intel 為全新類型的 PC 固件的體系結構、接口和服務提出的建議標準。
grub??????????????????????????? <===開機管理程序grub相關數據目錄
initramfs-2.6.32-71.el6.i686.img<===虛擬文件系統文件(RHEL6用initramfs代替了initrd,他們的目的是一樣的,只是本身處理的方式有點不同--
精通initramfs構建step by step--
http://blogold.chinaunix.net/u2/63991/showart_1856670.html
)
initrd-2.6.32-71.el6.i686.img??? <===此文件是linux系統啟動時的模塊供應主要來源,initrd的目的就是在kernel加載系統識別cpu和內存等內核信息之后,讓系統進一步知道還有那些硬件是啟動所必須使用的;
symvers-2.6.32-71.el6.i686.gz??? <===模塊符號信息
System.map-2.6.32-71.el6.i686??? <===是系統kernel中的變量對應表;(也可以理解為是索引文件)
vmlinuz-2.6.32-71.el6.i686??????? <===系統使用kernel,用于啟動的壓縮內核鏡像, 它也就是/arch/<arch>/boot中的壓縮鏡像.
Linux內核是可以通過動態加載內核模塊的 (就請想成驅動程序即可),這些內核模塊就放在 /lib/modules/目錄內。由于模塊放到磁盤根目錄內(這就是為什么/lib不可以與 / 分別放在不同的分區原因), 因此在開機的過程中內核必須要掛載根目錄,這樣才能夠讀取內核模塊提供加載驅動程序的功能。 而且為了擔心影響到磁盤內的文件系統,開機過程中根目錄是以只讀的方式來掛載的。
了解/boot/initrd這個文件
虛擬文件系統(Initial RAM Disk) 一般使用的文件名為 /boot/initrd ,這個文件的作用是,能夠通過 boot loader 來加載到內存中, 然后這個文件會被解壓縮并且在內存當中仿真
成一個根目錄, 且此仿真在內存當中的文件系統能夠提供一支可執行的程序,通過該程序來加載開機過程中所最需要的內核模塊,通常這些模塊就是 USB, RAID, LVM, SCSI 等文件系統與磁盤接口的驅動程序。等載入完成后,會幫助內核重新呼叫 /sbin/init 來開始后續的正常開機流程。
下面讓我們來看看initrd文件的具體內容,
[root@yufei ~]# mkdir tmp
[root@yufei ~]# cd tmp/
[root@yufei tmp]# cp /boot/initrd-2.6.32-71.el6.i686.img ./
[root@yufei tmp]# file initrd-2.6.32-71.el6.i686.img
initrd-2.6.32-71.el6.i686.img: gzip compressed data, from Unix, last modified: Thu Dec 16 00:29:07 2010, max compression
我們可以看到,這個文件是GZIP壓縮的文件,我們把后綴改成gz,然后再進行解壓
[root@yufei tmp]# mv? ?initrd-2.6.32-71.el6.i686.img????????? ?initrd-2.6.32-71.el6.i686.gz
[root@yufei tmp]# gunzip initrd-2.6.32-71.el6.i686.gz
解壓后,我們再來看看這個文件是什么類型的
[root@yufei tmp]# file initrd-2.6.32-71.el6.i686
initrd-2.6.32-71.el6.i686: ASCII cpio archive (SVR4 with no CRC)
是cpio壓縮成的文件
[root@yufei ~]# cpio -iv < initrd-2.6.32-71.el6.i686
[root@yufei tmp]# ls -l
總用量 30084
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 bin
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 cmdline
drwxr-xr-x. 3 root root???? 4096 12月 30 19:56 dev
-rw-r--r--. 1 root root?????? 18 12月 30 19:56 dracut-004-32.el6
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 emergency
drwxr-xr-x. 7 root root???? 4096 12月 30 19:56 etc
-rwxr-xr-x. 1 root root???? 8088 12月 30 19:56 init
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 initqueue
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 initqueue-finished
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 initqueue-settled
-rw-r--r--. 1 root root 30709760 12月 30 19:54 initrd-2.6.32-71.el6.i686
drwxr-xr-x. 9 root root???? 4096 12月 30 19:56 lib
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 mount
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 pre-pivot
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 pre-trigger
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 pre-udev
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 proc
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 sbin
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 sys
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 sysroot
drwxr-xr-x. 2 root root???? 4096 12月 30 19:56 tmp
drwxr-xr-x. 6 root root???? 4096 12月 30 19:56 usr
drwxr-xr-x. 3 root root???? 4096 12月 30 19:56 var
看到結果了吧,和我們系統中的/是不是很類似。有興趣的朋友,慢慢了解吧!哈哈……
init及配置文件 /etc/inittab 與 runlevel
在內核加載完畢、進行完硬件檢測與驅動程序加載后,此時主機硬件已經準備就緒了,這時候內核會主動的呼叫第一支程序,那就是 /sbin/init
/sbin/init 最主要的功能就是準備軟件執行的環境,包括系統的主機名、網絡設定、語言、文件系統格式及其他服務的啟動等。 而所有的動作都會通過 init的配置文件/etc/inittab來規劃,而inittab 內還有一個很重要的設定內容,那就是默認的 runlevel (開機運行級別)。
先來看看運行級別Run level
Linux就是通過設定run level來規定系統使用不同的服務來啟動,讓Linux的使用環境不同。我們來看看這個inittab文件里面的支持級別(RHEL6系統里面的,和以前的其它版本有很大的差別)
[root@yufei ~]# vim /etc/inittab
……
17 # Default runlevel. The runlevels used are:
18 #?? 0 - halt (Do NOT set initdefault to this)
19 #?? 1 - Single user mode
20 #?? 2 - Multiuser, without NFS (The same as 3, if you do not have netwo??? rking)
21 #?? 3 - Full multiuser mode
22 #?? 4 - unused
23 #?? 5 - X11
24 #?? 6 - reboot (Do NOT set initdefault to this)
……
? 0 - halt (系統直接關機)
? 1 - single user mode (單人維護模式,用在系統出問題時的維護)
? 2 - Multi-user, without NFS (類似底下的 runlevel 3,但無 NFS 服務)
? 3 - Full multi-user mode (完整含有網絡功能的純文本模式)
? 4 - unused (系統保留功能)
? 5 - X11 (與 runlevel 3 類似,但加載使用 X Window)
? 6 - reboot (重新啟動)
0, 4, 6 不是關機、重新啟動就是系統保留的,所以不能將預設的run level設定為這三個值。
RHEL6系統上的這個文件和以前的版本有很大的差別,目前這個文件只能設置運行級別,其它的相關配置文件,在此文件中已經做了說明如:
System initialization is started by /etc/init/rcS.conf
Individual runlevels are started by /etc/init/rc.conf
Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,with configuration in /etc/sysconfig/init.
更多的內容,大家可以到/etc/init/里面看看
從這個文件我們已經看出,紅帽已經使用新的Upstart啟動服務來替換以前的init,想了解更多,請參考http://www.opsers.org/2010_12_1500.html
在RHEL6的版本中,我們可以把/etc/init/這個目錄里面的內容,看成是以前/etc/inittab這個文件里的拆分。
下面是RHEL6上面Upstart大致的一個啟動過程:
1.內核啟動init
2.系統初始化:(/etc/init/rcS.conf exec /etc/rc.d/rc.sysinit)
3.init找到/etc/inittab文件,確定默認的運行級別(X) (/etc/init/rcS.conf exec telinit $runlevel)
4.觸發相應的runlevel事件(/etc/init/rc.conf exec /etc/rc.d/rc $RUNLEVEL)
5.開始運行/etc/rc.d/rc,傳入參數X
6./etc/rc.d/rc腳本進行一系列設置,最后運行相應的/etc/rcX.d/中的腳本
7./etc/rcX.d/中的腳本按事先設定的優先級依次啟動
8.最后執行/etc/rc.d/rc.local
9.加載終端或X-Window接口
想要了解更多的內容,請大家打開/etc/init/這個目錄里面的文件看看。
/etc/rc.sysinit 這個文件干了哪些工作?
vim /etc/rc.sysinit
1、獲得網絡環境
2、掛載設備
3、開機啟動畫面Plymouth(取替了過往的 RHGB)
4、判斷是否啟用SELinux
5、顯示于開機過程中的歡迎畫面
6、初始化硬件
7、用戶自定義模塊的加載
8、配置內核的參數
9、設置主機名
10、同步存儲器
11、設備映射器及相關的初始化
12、初始化軟件磁盤陣列(RAID)
13、初始化 LVM 的文件系統功能
14、檢驗磁盤文件系統(fsck)
15、磁盤配額(quota)
16、重新以可讀寫模式掛載系統磁盤
17、更新quota(非必要)
18、啟動系統虛擬隨機數生成器
19、配置機器(非必要)
20、清除開機過程當中的臨時文件
21、創建ICE目錄
22、啟動交換分區(swap)
23、將開機信息寫入/var/log/dmesg文件中
這個文件里面的許多預設配置文件在/etc/sysconfig/這個目錄當中,要想更多的系統啟動信息,大家可以到/var/log/dmesg文件中查看,也可以用dmesg命令來查看。
系統服務的啟動
經過 /etc/rc.sysinit 的系統模塊與相關硬件信息的初始化后,我們的RHEL6系統應該已經能順利工作了。但我們還需要啟動一些為我們提供服務的服務。這個時候,依據在/etc/inittab里面run level的設定值,就可以來決定啟動的服務項目了。
大家可以打開/etc/rc這個文件來研究
我們以運行級別3來說明
ls /etc/rc3.d/
在這個目錄下的文件主要具有2個特點:
1、全部以Sxx或Kxx(xx為數字)開頭
2、全部是連結文件,連結到/etc/init.d/
現在來說明一下這些的目的
S表示啟動服務
K表示停止服務
后面的數字是啟動的先后順序
我們以S00microcode_ctl來舉例
[root@yufei ~]# ls -l /etc/rc3.d/S00microcode_ctl
lrwxrwxrwx. 1 root root 23 12月 15 22:40 /etc/rc3.d/S00microcode_ctl -> ../init.d/microcode_ctl
他的意思就是
S00microcode_ctl=/etc/init.d/microcode_ctl start
而且是第一個啟動的服務。這樣我想大家應該明白了吧。
用戶自定義開機啟動腳本
上面講到的都是一些系統服務,大家知道,我們的Linux系統容許安裝其它的軟件來提供服務,那我想要自己安裝的服務也要在開機啟動,那怎么辦,沒有關系,找 /etc/rc.local 來完成。這就是我們要講的用戶自定義開機啟動腳本。我們只要把想啟動的腳本寫到這個文件中,開機就能啟動了,注意一點,寫在這里面的腳本要使用絕對路徑。
加載終端或X-Window接口
在完成了系統所有服務的啟動后,接下來Linux就會啟動終端或者是X Window來等待使用者登陸了!
在/etc/init/start-ttys.conf中我們可以看到有6個純文本終端(tty[1-6])。我們可以用[Ctrl+Alt+F1~F6]來切換這些終端。如果要切換到X window終端我們可以用[Ctrl+Alt+F7]
運行級別的切換
通過上面的學習,我們知道run level是在/etc/rc.sysinit 執行完畢之后,而run level 的不同之處僅是/etc/rc[0-6].d 里面啟動的服務不同而已。如果我們切換run level只需要停止與啟動一些服務就OK,那么要如何來實現,其它很簡單,用init n(數字)來切換。
比如說,我們要把運行級別5換成3,我們就用init 3來實現,切換的時候系統做了哪些事,我們來看看
先對比 /etc/rc3.d/ 及 /etc/rc5.d 內的 K 與 S 開頭的文件;
對比/etc/rc3.d/ 內有多余的 K 開頭文件則予以關閉;
對比/etc/rc3.d/ 內有多余的 S 開頭文件則予以啟動;
兩個 run level 都存在的服務就不會被關閉;
是不是很簡單,而且還不需要重新啟動。如果說我想關機或重新啟動系統,是不你已經想到了如何通過init來實現。哈哈……
http://www.opsers.org/2010_12_1518.html
想編譯內核,突然想知道linux的啟動過程,之后就想起來byr論壇有個人問過這個問題,翻了一下,找到了,地址在 這 。
當用戶打開PC的電源,BIOS進行開機自檢,按BIOS中設置的啟動設備(通常是硬盤)啟動,接著啟動設備上安裝的引導程序lilo或grub開始引導Linux,Linux首先進行內核的引導,接下來執行init程序,init程序調用了rc.sysinit和rc等程序,當rc.sysinit和rc完成系統初始化和運行服務的任務后,返回init;init啟動了mingetty后,打開了終端供用戶登錄系統,用戶登錄成功后進入了Shell,這樣就完成了從開機到登錄的整個啟動過程。
感覺這段寫的挺易懂的,之后帖子里邊還有一個鏈接,是一個pdf文檔,講linux啟動過程的,看了一遍,現記錄如下:
當PC機上電后,會將控制權轉移給BIOS的程序,BIOS通常固化在ROM中。BIOS并不是十分強大,但是它會完成兩個重要的任務:
-
第一個任務就是開機自檢(POST:Power On Self Test),這是對電腦硬件的一個整體狀況的檢測和初始化過程。BIOS瀏覽電腦中的
所有組件,并且執行所有需要的初始化。在現今的系統中,復雜的組件都提供他們自己的初始化規則,而BIOS的任務就是安排這些規則的執行順序。 - 第二個任務是BIOS會瀏覽啟動設備列表來尋找一個啟動加載器(bootloader),典型的啟動設備列表的內容和順序如下:軟盤(floppy)、CD 和/或DVD,一個或者多個硬盤驅動器。對于每個設備BIOS會讀取它的第一個分區(very first sector of the drive,這個分區被稱為啟動分區),直到找到了一個提供啟動加載器(boot loader)的啟動分區。boot loader是一個輕量級但是很強大的程序,它的任務就是將操作系統引導到內存中,并且開始運行。
- 如上的過程只是系統啟動的框架,并未詳述BIOS或者bootloader具體的工作。
對于Linux來說,通常的bootloader是GRUB(Grand Unified Bootloader)。事實上,GRUB太大,不能放在一個硬盤分區內。所以它被分為兩部分:小的那部分放在啟動分區內(boot sector),它的主要任務就是找到并且加載大的那個部分,而大的部分的任務就是找到并且加載操作系統。
如果你的PC是多操作系統的(如Linux和Windows),上述的那一步就是選擇啟動哪個系統的位置。
一旦加載到了內存并且由bootloader啟動了,Linux內核就隨著它的啟動執行一系列的動作:
- 首先他將瀏覽硬件配置,初始化設備驅動器,并且將CPU設置為帶有虛擬內存的保護模式;
- 其次,它掛載根文件系統(只讀);
- 最后,一旦這些準備都完成了,內核將啟動一個用戶進程:/sbin/init,這個用戶進程負責啟動的所有后續工作。
init程序的進程ID是1,是程序樹的根節點。系統中運行的所有程序都是他的后代。init將會一直運行知道系統掛掉(halt),同時我們將看到它全面負責系統的狀態。
多年以來的init文件參考的是19世紀80年代的SysV(Unix) System V)的init。最近有了一些變化,但是所有我熟悉的新的實現都考慮到了SysV的框架并且向后兼容SysV的init文件。當init啟動,init尋找/etc/inittab文件執行其中的指令使啟動過程向下進行。如下是一個來自ubunt工作站的nittab文件,進行了少許修改減小了尺寸。
# /etc/inittab: init(8) configuration.
# longan.csil.sfu.ca, slightly edited for size
# The default runlevel.
id:2:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin
~~:S:respawn:sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
# Action on special keypress (ALT-UpArrow).
#kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."
# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop
# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Note that on most Debian systems tty7 is used by the X Window System,
# so if you want to add more getty’s go ahead but skip tty7 if you run X.
#
1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6
可以看出inittab中每行的格式為:id:runlevel(s):action:command
?
其中
- id 只是一個為了方便的標識,對init沒有什么特殊意義;
- command 要么是可執行命令,要么是一個程序,要么就是一個腳本;
- runlevel 和 action 要控制什么時候和怎樣執行 command ,隨著我們的深入,這個將會更加明顯。
init在inittab中第一個要找的就是 action 域為’sysinit’的那一行。這個就是在系統啟動時應該執行的命令。
- 在Ubuntu 6發行版中, action 域為’sysinit’的那個命令關聯的是/etc/init.d/rcS這個腳本。查看一下rcS發現它執行的其實是命令’/etc/init.d/rc S’,rc腳本是一個類屬腳本(generic script),這個腳本尋找目錄/etc/rcN.d(N為數字),并且執行相應目錄中的所有腳本。
- 所以,如果系統執行level 5,那么rc尋找目錄/etc/rc5.d
在/etc/rcN.d目錄中,都是以S或者K開頭的腳本,并且后邊緊接數字,格式如下[S|K]dd,其中dd是數字。
- 以S或者K開頭的腳本要么就是啟動或者殺死某些服務的腳本,要么就是設置服務的腳本。當進入某啟動模式后,rc腳本將先執行殺死腳本,緊接著在執行啟動腳本;
- 兩個數字dd范圍是00到99.這個數字決定了在啟動腳本和殺死腳本中的執行順序;
- 文件名中的命令部分用來指示那個系統或者系統組被這個腳本操控。(The command portion of the file name is chosen to indicate which system or group of systems is manipulated by the script.)
- 如果使用’ls -F‘或者’ls -l‘查看rcN.d文件夾的文件列表的話,將發現這些腳本實際是符號鏈接,鏈接到/etc/init.d中的腳本。通常,每個腳本都有四個執行參數:start、stop、status和restart;有一些有額外參數。
讓我們回到命令’rc S‘會產生怎樣的結果。在rcS.d文件夾中,一個由腳本執行的不完整的函數列表包括:
- 隨著啟動一系列的進程,設置系統配置變量,使用的值包含在/etc/default文件中;
- 繼續初始化如下設備:usb,clock,keyboard和disk handling的優化;
- 清除系統狀態文件;
- 啟動網絡接口(對于這一步/etc/sysctl.conf文件很重要);
- 使用NFS掛載遠程文件系統。
當rc S完成/etc/rcS.d中腳本的執行后,將控制權返還給init,init在inittab中繼續尋找 action 域是’initdefault‘的那一行。這個入口沒有附帶的命令,它的作用是說明應該啟動哪個run level來完成啟動過程。
此時解釋run level恰到好處。通常的unix系統,run level就是0-6之間的整數,這些整數用來說明系統的狀態(通常叫做模式)。
如下是Ubuntu Linux的run level的典型設置:
- 0:停止系統;將run level設置為零將導致Linux進行有序的shutdown,并且關掉電腦;
- 1:單用戶模式;在這個狀態,之后內核和一些極其重要的服務運行。這個狀態用作系統維護、升級和修復,這些工作都不能在普通模式下完成。(通常,當任務正 在進行中時,因為系統狀態不會一成不變,因此是不安全的。同時排除了其他用戶的不必要的系統行為。)
- 2-5:多用戶模式;系統在這個狀態,可以支持多用戶和提供GUI界面;
- 6:重啟模式;系統 halt ,之后緊接著自動進行重啟。
這些run level都是慣例;所有的unix系統都遵從相同的啟動順序,具體的run level與系統模式之間的映射關系可能各不相同(如Fedora,分了許多多用戶模式,最小啟動和最小啟動+掛載遠程文件系統和GUI界面)。
我們接著解釋余下的開機行為。
?
sysinit | 在啟動時間具體執行的命令 |
initdefault | 默認的run level;沒有相關的命令 |
powerfailnow | 發現掉電時具體執行的命令 |
ctrlaltdel | 當用戶通過ctl+alt+del組合鍵強制重啟時,需要執行的命令 |
once |
只啟動一次的命令。init不會等待相應命令的完成(Speci?es that the command is to be started exactly once;
init will not wait for completion) |
wait | 只執行一次的命令,并且 init 在執行之前會等待響應命令完成。(這是通常的行為,同樣應用到sysinit,ctrlaltdel和powerfail命令) |
respawn | 開始命令并且監視它;如果它一直不結束,就再次執行該命令。這個行為用于監視控制臺和其他登錄端口的行為。 |
?
除了列在這里的內容外,inittab還有其他的動作,具體參見man inittab。
一旦init知道了默認的run level,它將找到相應run level的那行,之后執行那行 action 域的相應命令。
- 隨著對run level S的初始化設置,一個給定的run level的工作將切換到/etc/init.d/rc,它在相應的run level下作為唯一的參數被執行。
其他函數將由腳本/etc/init.d控制。不完整列表如下:
- Internet服務(DNS,SNMP,SSH,plus the meta-daemon xinetd),和防火墻;
- 使用Samba的遠程的文件共享;
- 界面管理器(負責開啟GUI登錄界面)
- cron守護進程,它可以實現在特定時間內運行某個任務。
- 打印和登錄服務
- 網絡信息服務,也就是我們之前稱為的黃頁。設置一個由核心服務維護的數據庫,可以通過網絡發出請求。
- 遠程處理呼叫、遠程執行守護進程
對于inittab還有一件事需要提。inittab文件底部,有幾行內容的 id 域是數字的。這些行控制一些程序,來監聽登錄請求。
- 對于每個用戶可以登錄的端口–典型的就是通過串口登錄到終端–必須有個程序監聽的登錄請求。
- Debian使用名叫getty的程序;其他unix系統有不同的名字。這個程序負責監聽相應端口的行為,并且當它檢測到相關行為時,顯示一個登錄提示符。當你輸入了正確的用戶名和密碼,getty將啟動一個命令行shell,開始你的工作。
最近,一個叫做upstart的新的init實現投入了使用。為了兼容SysV系統的init,upstart的二進制執行文件也叫做init。為了避免一些不必要的混淆,這章將指定upstart或者init,而避免使用二進制的名稱。upstart使用在Ubuntu7中,安裝在網絡實驗室的虛擬工作站中。
- upstart的操作是基于事件概念的,并且通過事件的發生與否來觸發upstart的行為。
- 開始階段,upstart對由/etc/event.d文件夾中的文件定義的工作進行確認。
- 為了使時間滾動,當upstart意識到自己是進程1時,upstart將執行startup事件。
為了與SysV的nit兼容,upstart的事件定義與SysV的init幾乎是一一對應的。
- 事件rcS,由startup事件觸發,執行/etc/init.d/rcS
- 當rcS結束,執行一個stopped rcS事件,這個事件觸發rc-default事件。你可能已經從這個名字猜到了,這個任務決定了默認的run level
。它執行一個run level N事件。
- run level N事件觸發一個執行rcN腳本的任務
- 最后,完成對getty程序的初始化,并且監聽登錄請求。
對于init進程有其他變種,如,sun solaris使用的是服務管理套件。
你可能注意到了,在inittab中有六個入口監聽登錄請求。
現在我們來看看在只有一個控制臺的情況下為什么會有六個入口。
- Linux提供了一個工具叫做虛擬控制臺(通常指的就是虛擬終端)。大多數Linux系統配置了7個。
- 每一個都提供了獨立的登入端口,就像電腦為終端提供了7個分離的輸入/輸出連接。特別的,當你在一個虛擬終端登出,并不會使其他虛擬終端也登出。
- 約定,虛擬終端1-6用作命令行登錄,虛擬終端7用作GUI登錄。
- 在各個虛擬終端之間切換用組合鍵‘alt+Fn’,其中n是1-7。對于擺脫GUI>登錄界面有點不同;需要組合鍵‘ctrl+alt+Fn來切換到其他虛擬終端。
虛擬控制臺1-6提供了命令行登錄方式
- 一旦進入了系統,一個命令行shell就開始工作。unix命令行shell模擬的是DOS命令行shell,但是他們的功能是截然不同的。
- 有多種不同的shell,你登入系統得到的哪種shell由/etc/passwd文件中你的相應行決定。得到的第一個shell叫做登錄shell。
-
如下是對unix shel的簡單分類:
shell init file Comments sh .profile 最原始的shell,但是仍然是重要,因為許多主要系統的shell腳本都是按這個shell寫的 ksh .profile (korn shell)sh的加強版 bash .bashrc 對sh版的極大的加強版 csh .cshrc “C”shell,可與sh媲美,不過csh有跟人性化的高亮功能 tcsh .tcshrc ”Tenex“ C shell,csh的極大加強版 ????
sh和他的后代ksh、bash具有同樣的句法結構。這些shell提供的原始的操作是將文本串分割成獨立的字母。他們還能提供出色的輸入/輸出重定向。
csh和他的后代tcsh同樣具有相同的句法結構,但是不同于sh和sh的后代。csh和他的后代將文本串分割成單詞。輸入/輸出重定向也顯得粗陋。 - 一旦登錄shell運行,他將會尋找相應的初始化文件。正如上邊所示,不同shell的初始化文件也各不相同。如果家目錄中沒有初始化文件,通常會使用在/etc中的默認文件。
- 每當你執行新的命令行shell初始化文件就被執行一次。但是登錄shell(當你登入之后的第一個shell)會執行第二個初始化文件,叫做.login(.bash_login for bash).同樣,它會在你的系統家目錄中找這個文件。
- 當登錄shell完成了自身的初始化,他將提供一個提示符,此時你就可以工作了。
虛擬終端7不同于其他虛擬終端:它提供了一個GUI登錄界面。
- 這個登錄界面看起來很熟悉—它提供了輸入用戶名和密碼的地方,還有一些其他選項
- 屏幕呈現出一個簡潔的X Window System管理界面,Linux可以通過它選擇要提供的服務
- 為了進一步解釋這發生了什么,我們需要后退一步談一談X Window System
-
come from:
http://zhumeng8337797.blog.163.com/blog/static/10076891420112103132464/?suggestedreading&wumii
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
