淺談Linux啟動過程

2020-08-29 Kasar

和Window等其他作業系統一樣,linux的啟動也分為兩個階段:引導(boot)啟動(startup)引導階段開始於打開電源開關,接下來板載程序BIOS的開始POST上電自檢主過程,結束於內核初始化完成。啟動階段接管剩餘的工作,直到作業系統初始化完成進入可操作狀態,並能夠執行用戶的功能性任務。

我們不花過多篇幅講解引導階段的硬體板載程序加載運行的過程。事實上,由於在板載程序上很多行為基本上固定的,程式設計師很難介入,所以接下來主要講講主板的引導程序如何加載內核程序以及控制權交給linux作業系統之後的各個服務的啟動流程。

GRUB引導加載程序

所謂引導程序,一個用於計算機尋找作業系統內核並加載其到內存的智能程序,通常位於硬碟的第一個扇區,並由BIOS載入內存執行。為什麼需要引導程序,而不是直接由BIOS加載作業系統?原因是BOIS只會自動加載硬碟的第一個扇區的512位元組的內容,而作業系統的大小遠遠大於這個值,所以才會先加載引導程序,然後通過引導程序加載程序加載作業系統到內存中。

目前,各個Linux發行版主流的引導程序是GRUB(GRand Unified BootLoader)。GRUB的作用有以下幾個: - 加載作業系統的內核 - 擁有一個可以讓用戶選擇到底啟動哪個系統的的菜單界面 - 可以調用其他的啟動引導程序,來實現多系統引導

GRUB1現在已經逐步被棄用,在大多數現代發行版上它已經被GRUB2所替換。GRUB2通過/boot/grub2/grub.cfg進行配置,最終GRUB定位和加載linux內核程序到內存中,並轉移控制權到內核程序。

內核程序

內核程序的相關文件位於/boot目錄下,這些內核文件均帶有前綴vmlinuz。內核文件都是以一種自解壓的壓縮格式存儲以節省空間。在選定的內核加載到內存中並開始執行後,在其進行任何工作之前,內核文件首先必須從壓縮格式解壓自身。

ps -ef

UID PID PPID C STIME TTY TIME CMD

root 1 0 0 Mar29 ? 00:00:17 /sbin/init

root 2 0 0 Mar29 ? 00:00:00 [kthreadd]

root 3 2 0 Mar29 ? 00:00:22 [ksoftirqd/0]

root 5 2 0 Mar29 ? 00:00:00 [kworker/0:0H]

...

定義、管理和控制init進程的系統被稱為init系統。我們知道僅僅將內核運行起來是沒有什麼實際意義,必須由init系統將整個linux作業系統代入可操作狀態。init系統主要的任務就是去運行這些開機啟動的程序。但是,不同的場合需要啟動不同的程序來進入不同的預設運行模式。例如,啟動shell進行人機互動,這樣就可以讓計算機執行一些預訂程序完成有實際意義的任務,啟動X圖形系統以便提供友好的人機界面,更加高效的完成任務。這裡,命令行界面的shell或者X圖形界面都是一種預設的運行模式。

Init系統的歷史

大多數linux發行版的init系統是和System V相兼容的,被稱為SysVInit,這就是最初的init系統。在linux主要應用於伺服器和PC機的時代,SysVInit運行概念簡單清晰,運行穩定。但是它主要依賴於Shell腳本,導致啟動速度太慢。這點在很少重啟的伺服器上並沒有多少影響,而隨著linux內核的不斷演化發展linux作業系統越來越多地被應用到移動終端設備的時候,啟動慢就嚴重影響用戶體驗,被越來越多人詬病。

為了解決啟動慢的問題,人們開始思考改進SysVInit,先後出現了UpStart和Systemd這兩個主要的新一代init系統。UpStart已經開發了8年多,在不少系統中已經替換SysVInit,而Systemd出現比較晚,但發展更快,大有取代UpStart統治各個linux發行版的趨勢。事實上,Ubuntu和RHEL採用UpStart替代了傳統的SysVInit。而Fedora發行版則從版本15開始使用Systemd。

SysVInit

對於使用SysVInit的老式linux發行版來說,使用「運行級別」(Run Level)來定義」預訂的運行模式」。這樣的linux發行版一般預置七種運行級別(0-6)。通常情況下,0代表關機,1代表單用戶模式(也就是維護模式),6代表重啟。運行級別2-5,各個發行版不太一樣,但基本都是多用戶模式(也就是正常模式)。

init進程首先讀取檢查運行級別的設置文件/etc/inittab是否含有initdefault項,它代表系統默認的運行級別;如果沒有默認運行級別,那麼就需要用戶進入系統控制臺手動決定進入何種運行模式。運行級別的設置文件/etc/inittab的第一行一般是這樣的:

id:2:initdefault:

這代表系統啟動時的默認運行級別為2,如果需要指定其他級別,需要手動修改這個值。

但是問題來了,在不同的運行級別中,系統需要初始化運行的服務進程和需要進行的初始化準備都是不同的,有些linux發行版的運行級別3不需要啟動X圖形界面系統。系統怎麼知道每個級別應該加載哪些程序呢?…回答是每個運行級別在/etc目錄下面,都有一個對應的子目錄,指定要加載的服務程序。這樣,用戶只需要指定需要進入哪種運行級別,SysVInit將負責執行所有該級別下必須的初始化工作。

ll /etc/rc2.d

total 20

lrwxrwxrwx 1 root root 16 Aug 20 2018 K01autofs -> ../init.d/autofs*

-rw-r--r-- 1 root root 677 Feb 5 2016 README

lrwxrwxrwx 1 root root 16 Aug 20 2018 S01apport -> ../init.d/apport*

lrwxrwxrwx 1 root root 17 Aug 20 2018 S01rsyslog -> ../init.d/rsyslog*

lrwxrwxrwx 1 root root 15 Aug 20 2018 S01uuidd -> ../init.d/uuidd*

lrwxrwxrwx 1 root root 17 Aug 20 2018 S02postfix -> ../init.d/postfix*

lrwxrwxrwx 1 root root 15 Aug 20 2018 S02rsync -> ../init.d/rsync*

lrwxrwxrwx 1 root root 13 Aug 20 2018 S02ssh -> ../init.d/ssh*

...

我們看到,除了README以外,其他文件名都是」字母S+兩位數字+程序名」的形式。字母S表示Start,代表在當前級別下運行啟動對應程序;字母K,就代表Kill,即從其他運行級別切換過來時需要關閉的程序;後面的兩位數字表示處理順序,數字越小越早處理,所以第一個啟動的程序是apport,然後是rsyslog、uuidd、postfix…數字相同時,則按照程序名的字母順序啟動,所以rsyslog會先於uuidd啟動。

同時,我們也注意到,/etc/rcN.d目錄裡列出的程序其實都設為符號連結,指向另外一個目錄/etc/init.d下真正的程序啟動腳本,init進程逐一加載開機啟動程序,其實就是運行這個目錄裡的啟動腳本。這樣做的好處是就是如果需要手動關閉或重啟某個進程,直接到目錄/etc/init.d中尋找對應的啟動腳本即可。比如,要重啟ssh服務,只需要運行下面的命令:

/etc/init.d/ssh restart

Upstart

當linux內核進入2.6之後,內核的很多功能完全適用於桌面系統甚至嵌入式設備,於是開發人員就開始嘗試將linux移植的工作。最具有代表性的是Ubuntu的開發人員Scott James Remnant,他曾試圖將linux安裝在筆記本電腦上,但發現老式的SysVInit並不適合桌面系統或可攜式設備,原因是:

  • 桌面系統或可攜式設備的特點是經常重啟,而且要頻繁地使用硬體熱插拔技術,而SysVInit沒有辦法處理這類按需啟動外設的需求
  • 網絡共享盤的掛載問題,SysVInit在網絡初始化之前分析/etc/fstab來發現響應的掛載文件以及掛載位置,但如果網絡沒有啟動,類似於NFS或者iSCSI的網絡共享盤都不可訪問,當然也無法進行掛載操作。

針對以上SysVInit的不足,Ubuntu開發人員決定重新設計和開發一個全新的init系統,也就是UpStart。

UpStart基於事件機制,例如U盤插入USB接口後,udev得到內核通知,發現新設備接入,這就是一個新的事件。UpStart在感知到該事件之後觸發相應的等待任務,比如處理/etc/fstab中存在的掛載點。採用這種事件驅動的模式,UpStart完美地解決了即插即用設備帶來的新問題,同時通過並行啟動程序顯著減少系統啟動時間。

在上面的例子中,有7個不同的程序需要啟動:Job A、Job B…Job F。在SysVInit中,每一個啟動項目都由一個獨立的腳本負責,它們由SysVInit按照順序串行調用。因此總的啟動時間為T1+T2+T3+T4+T5+T6+T7。其中一些任務有依賴關係,比如A,B,C,D,而E和F卻和A,B,C,D無關。這種情況下,UpStart能夠並發地運行任務{(A,B,C),(D,E),F},使得總的啟動時間減少為T1+T2+T3。這無疑增加了系統啟動的並行性,從而提高了系統啟動速度。但是在UpStart中,有依賴關係的服務還是必須先後啟動串行執行,比如任務{(A,B,C)}。

在UpStart中主要的概念是job和event。所謂job其實就是完成特定任務的工作單元,例如啟動一個後臺服務,或者運行一個配置命令。每個job都等待響應一個或多個event,一旦獲取到響應的event,UpStart就觸發該對應的job完成相應的工作。使用UpStart的linux發行版系統初始化的過程是在job和event的相互協作下完成的,可以大致描述如下:內核初始化完成之後,init進程開始運行,init進程自身會發出不同的event,這些最初的event會觸發一些job運行;而每個job運行過程中會釋放新的不同的event,這些event又將觸發新的job運行,如此反覆,直到整個系統正常運行起來。

那麼,哪些event會觸發某個job的運行?這是由」job配置文件」定義的。任何一個job都是由一個job配置的文本文件定義的。這個文件包含多個部分,每個部分是一個完整的定義模塊,定義了job的一個方面,比如author部分定義了工作的作者。工作配置文件存放在/etc/init目錄下面,以.conf作為文件後綴的文件。下面,我們就來看看linux下面cron的job配置文件定義:

cron - regular background program processing daemon

cron is a standard UNIX program that runs user-specified programs at

34;regular background program processing daemon&cat /etc/system/system/sshd.service

[Unit]

Description=OpenSSH server daemon

[Service]

EnvironmentFile=/etc/sysconfig/sshd

ExecStartPre=/usr/sbin/sshd-keygen

ExecStart=/usrsbin/sshd –D $OPTIONS

ExecReload=/bin/kill –HUP $MAINPID

KillMode=process

Restart=on-failure

RestartSec=42s

[Install]

WantedBy=multi-user.target

可以看到,SSH服務配置單元文件分為三個部分:第一個是[Unit]部分,這裡僅僅包含一個簡短的描述信息;第二部分是[Service]定義,其中ExecStartPre定義啟動服務之前應該運行的命令,ExecStart定義啟動服務的具體命令行語法;第三部分是[Install],WangtedBy表明這個服務是在多用戶模式下所需要的。

既然說到多用戶模式,那就來看看multi-user.target的配置單元,它屬於target類型的配置單元:

34;$BASH_VERSION&34;$HOME/.bashrc&34;$HOME/.bashrc"

fi

fi

總之,不管是哪種情況,.bashrc在用戶登錄的時候都會執行,用戶的設置可以放心地都寫入這個文件了。

之所以有這麼繁多複雜的登錄設置文件是由於歷史原因造成的。在linux出現早期的時候,計算機運行速度很慢,載入配置文件需要很長時間,多數Shell的作者只好把配置文件分成了幾個部分,階段性載入。系統的通用設置放在/etc/profile,用戶個人的、需要被所有子進程繼承的設置放在.profile,不需要被繼承的設置放在.bashrc。

相關焦點

  • 淺談分析Arm linux 內核移植及系統初始化的過程二
    具體註冊和註銷過程在下一節介紹。4.3. 處理器、設備4.4.);//setup processor and machine and destinate some pointers for do_initcalls() s5、淺談分析Arm linux 內核移植及系統初始化的過程 諮詢QQ:313807838// for example init_machine
  • 聊聊Linux的啟動過程
    本文介紹Linux的開機過程,文章內容針對從事雲計算、後端開發的同學以及熱衷Linux的朋友。依照 BIOS 設定,找到第一個可以啟動的設備(一般是硬碟);BIOS晶片中主要存放:自診斷程序:加電自檢(Power On Self Test,簡稱POST)通過讀取CMOSRAM中的內容識別硬體配置,並對其進行自檢和初始化;CMOS設置程序:引導過程中,用特殊熱鍵啟動,進行設置後,存入CMOS RAM中;系統自舉裝載程序
  • 簡述Linux的啟動過程
    本文將簡單介紹一下Linux的啟動過程,希望對那些安裝Linux的過程中遇到了問題的朋友有些幫助聲明: 本人沒用過UEFI模式和GPT
  • Linux啟動過程剖析
    Linux啟動過程的剖析能幫助那些想深入學習Linux用戶建立一個相關Linux啟動過程的清晰概念,進而可以進一步研究Linux接下來是如何工作的。本文引用地址:http://www.eepw.com.cn/article/148603.htmLinux啟動過程如下:當用戶打開PC的電源,BIOS開機自檢,按BIOS中設置的啟動設備(通常是硬碟)啟動,接著啟動設備上安裝的引導程序lilo或grub開始引導Linux,Linux首先進行內核的引導,接下來執行init程序,init程序調用了rc.sysinit和rc等程序,rc.sysinit
  • IT斷魂槍--閒聊Linux系統啟動過程
    Initrd*.img是一個精簡但帶了所有驅動的linux鏡像,一般系統安裝完之後自動生成,也可以事後手動生成。曾經某偏門軟體推薦用集成鏡像安裝,裝完了就是起不來,我把同內核版本、同硬體配置的init*.img替換以後系統就正常啟動。
  • 帶你閱讀linux內核源碼:linux內核啟動過程分析
    同樣的道理,當你接觸linux內核這位大美女的時候,你也會有上面的小心思,那我們就來看:linux內核從哪兒來? -- 內核是如何運行起來的,它的啟動過程是怎麼樣的?本文或者後續文章代碼均參考自:linux 4.9.230版本。
  • 詳解bootloader的執行流程與ARM Linux啟動過程分析
    ARM Linux啟動過程分析是本文要介紹的內容,嵌入式 Linux 的可移植性使得我們可以在各種電子產品上看到它的身影。對於不同體系結構的處理器來說Linux的啟動過程也有所不同。 本文以S3C2410 ARM處理器為例,詳細分析了系統上電後 bootloader的執行流程及 ARM Linux的啟動過程。
  • Linux基礎命令之: Linux啟動過程詳解
    本文引用地址:http://www.eepw.com.cn/article/257157.htm在了解了Linux的常見命令之後,下面詳細講解Linux的啟動過程。Linux的啟動過程包含了Linux工作原理的精髓,而且在嵌入式開發過程中非常需要這方面的知識。
  • 淺談zynq啟動,BootROM和FSBL等的執行過程
    本文主要介紹zynq啟動過程,主要包括BootROM和FSBL等的執行過程。 硬體啟動過程 1. 重新上電或POR復位後進行硬體啟動過程 2. 掃描「啟動引腳」設置,並存入只讀寄存器slcr.BOOT_MODE中 3.
  • uclinux啟動過程詳細分析
    本文引用地址:http://www.eepw.com.cn/article/201808/388126.htmuClinux啟動過程uCinux的啟動主要經歷三個階段。首先,必須完成CPU和存儲器的硬體初始化,在系統RAM中建立程序堆棧和數據段,建立程序的運行時的環境。
  • arm linux 啟動過程
    arm-linux啟動過程本文引用地址:http://www.eepw.com.cn/article/201611/318006.htm1. kernel運行的史前時期和內存布局在arm平臺下,zImage.bin壓縮鏡像是由bootloader加載到物理內存
  • 淺談SFTP、FTP的區別
    在linux系統中,最長使用到的文件傳輸的方式莫過於ftp和sftp了,但是這兩個傳輸方式有什麼本質不同呢?本文通過centos系統,給大家淺談SFTP、FTP的區別!FTP在linux系統中,傳輸默認的埠為21埠,通常以ASCII碼和二進位的方式傳輸數據,支持主動模式和被動模式兩種方式。
  • linux啟動到單用戶模式 - CSDN
    Linux啟動引導器安裝linux作業系統的時候就已經將啟動引導器安裝到硬碟上去了,才能通過硬碟的讀取方式啟動作業系統。引導器分為2種:Lilo:功能比較簡單,使用比較麻煩,後續發行版中使用grub。啟動引導器保存在硬碟扇區中,負責引導硬碟分區中指定的作業系統啟動的程序代碼。
  • linux 任務 啟動 定時 - CSDN
    一、開機自啟動任務。我們首先要明確開機自啟動是個什麼概念。開機自啟動的任務主要在兩個時間點發生,一個是用戶沒有登陸之前,系統正在啟動的過程中,另一個是用戶成功登陸之後(即通過登陸界面輸入用戶名密碼登陸之後)。
  • Linux系統啟動過程
    當電腦接通電源,電腦開始執行 BIOS(基本輸入輸出系統Basic I/O System)的 POST(上電自檢Power On Self Test)過程。在 1981 年,IBM 設計的第一臺個人電腦中,BIOS 被設計為用來初始化硬體組件。POST 作為 BIOS 的組成部分,用於檢驗電腦硬體基本功能是否正常。
  • 嵌入式Linux內核啟動主要分為這三個階段
    【IT168 資訊】嵌入式linux內核的啟動全過程主要分為三個階段。第一階段為內核自解壓過程,第二階段主要工作是設置ARM處理器工作模式、使能MMU、設置一級頁表等,而第三階段則主要為C代碼,包括內核初始化的全部工作,下面是詳細介紹。
  • 走進Linux之systemd啟動過程
    Linux系統的啟動方式有點複雜,而且總是有需要優化的地方。傳統的Linux系統啟動過程主要由著名的init進程(也被稱為SysV init啟動系統)處理,而基於init的啟動系統被認為有效率不足的問題,systemd是Linux系統機器的另一種啟動方式,宣稱彌補了以傳統Linux SysV init為基礎的系統的缺點。
  • linux內核啟動流程
    Linux內核啟動及文件系統加載過程   當u-boot開始執行bootcmd命令,就進入Linux內核啟動階段,與u-boot類似,普通Linux內核的啟動過程也可以分為兩個階段,但針對壓縮了的內核如uImage就要包括內核自解壓過程了。本文以linux-2.6.37版源碼為例分三個階段來描述內核啟動全過程。
  • Linux安全系列---啟動篇(上)
    Linux的自啟動項,相對Windows來說簡單太多了,在我們應急響應中作業系統的啟動方式有哪些這個是一定要知道的,不然後門也清除不乾淨啊。我們先說下linux的啟動過程,十幾年前某位黑闊大佬寫了一篇文章,說今天面試了一個腳本小子,讓他說出linux 的啟動過程,他嚶嚶嚶了半天沒嚶出個所以然來。看了以後,我也學會了,請問linux的啟動過程是什麼?
  • STM32的啟動過程是怎麼樣的?
    STM32的啟動過程是怎麼樣的? STM32嵌入式開發 發表於 2020-11-27 16:36:44 分享這篇文章,談一下STM32啟動流程。