導航:首頁 > 操作系統 > linux啟動原理

linux啟動原理

發布時間:2023-06-12 07:56:01

linux進程管理及作業控制的啟動進程

鍵入需要運行的程序的程序名,執行一個程序,其實也就是啟動了一個進程。在Linux系統中每個進程都具有一個進程號,用於系統識別和調度進程。啟動一個進程有兩個主要途徑:手工啟動和調度啟動,後者是事先進行設置,根據用戶要求自行啟動。 由用戶輸入命令,直接啟動一個進程便是手工啟動進程。但手工啟動進程又可以分為很多種,根據啟動的進程類型不同、性質不同,實際結果也不一樣,下面分別介紹。
1. 前台啟動
這或許是手工啟動一個進程的最常用的方式。一般地,用戶鍵入一個命令「ls –l」,這就已經啟動了一個進程,而且是一個前台的進程。這時候系統其實已經處於一個多進程狀態。或許有些用戶會疑惑:我只啟動了一個進程而已。但實際上有許多運行在後台的、系統啟動時就已經自動啟動的進程正在悄悄運行著。還有的用戶在鍵入「ls –l」命令以後趕緊使用「ps –x」查看,卻沒有看到ls進程,也覺得很奇怪。其實這是因為ls這個進程結束太快,使用ps查看時該進程已經執行結束了。如果啟動一個比較耗時的進程:
find / -name fox.jpg
然後再把該進程掛起,使用ps查看,就會看到一個find進程在裡面。
2. 後台啟動
直接從後台手工啟動一個進程用得比較少一些,除非是該進程甚為耗時,且用戶也不急著需要結果的時候。假設用戶要啟動一個需要長時間運行的格式化文本文件的進程。為了不使整個shell在格式化過程中都處於「癱瘓」狀態,從後台啟動這個進程是明智的選擇。
[例1]
$ troff –me notes > note_form &
[1] 4513
$
由上例可見,從後台啟動進程其實就是在命令結尾加上一個&號。鍵入命令以後,出現一個數字,這個數字就是該進程的編號,也稱為PID,然後就出現了提示符。用戶可以繼續其他工作。
上面介紹了前、後台啟動的兩種情況。實際上這兩種啟動方式有個共同的特點,就是新進程都是由當前shell這個進程產生的。也就是說,是shell創建了新進程,於是就稱這種關系為進程間的父子關系。這里shell是父進程,而新進程是子進程。一個父進程可以有多個子進程,一般地,子進程結束後才能繼續父進程;當然如果是從後台啟動,那就不用等待子進程結束了。
一種比較特殊的情況是在使用管道符的時候。例如:
nroff -man ps.1|grep kill|more
這時候實際上是同時啟動了三個進程。請注意是同時啟動的,所有放在管道兩邊的進程都將被同時啟動,它們都是當前shell的子程序,互相之間可以稱為兄弟進程。
以上介紹的是手工啟動進程的一些內容,作為一名系統管理員,很多時候都需要把事情安排好以後讓其自動運行。因為管理員不是機器,也有離開的時候,所以有些必須要做的工作而恰好管理員不能親自操作,這時候就需要使用調度啟動進程了。 有時候需要對系統進行一些比較費時而且佔用資源的維護工作,這些工作適合在深夜進行,這時候用戶就可以事先進行調度安排,指定任務運行的時間或者場合,到時候系統會自動完成這一切工作。
要使用自動啟動進程的功能,就需要掌握以下幾個啟動命令。
at命令
用戶使用at命令在指定時刻執行指定的命令序列。也就是說,該命令至少需要指定一個命令、一個執行時間才可以正常運行。at命令可以只指定時間,也可以時間和日期一起指定。需要注意的是,指定時間有個系統判別問題。比如說:用戶現在指定了一個執行時間:凌晨3:20,而發出at命令的時間是頭天晚上的20:00,那麼究竟是在哪一天執行該命令呢?如果用戶在3:20以前仍然在工作,那麼該命令將在這個時候完成;如果用戶3:20以前就退出了工作狀態,那麼該命令將在第二天凌晨才得到執行。下面是at命令的語法格式:
at [-V] [-q 隊列] [-f 文件名] [-mldbv] 時間
at -c 作業 [作業...]
at允許使用一套相當復雜的指定時間的方法,實際上是將POSIX.2標准擴展了。它可以接受在當天的hh:mm(小時:分鍾)式的時間指定。如果該時間已經過去,那麼就放在第二天執行。當然也可以使用midnight(深夜),noon(中午),teatime(飲茶時間,一般是下午4點)等比較模糊的詞語來指定時間。用戶還可以採用12小時計時制,即在時間後面加上AM(上午)或者PM(下午)來說明是上午還是下午。
也可以指定命令執行的具體日期,指定格式為month day(月 日)或者mm/dd/yy(月/日/年)或者dd.mm.yy(日.月.年)。指定的日期必須跟在指定時間的後面。
上面介紹的都是絕對計時法,其實還可以使用相對計時法,這對於安排不久就要執行的命令是很有好處的。指定格式為:now + count time-units ,now就是當前時間,time-units是時間單位,這里可以是 minutes(分鍾)、hours(小時)、days(天)、weeks(星期)。count是時間的數量,究竟是幾天,還是幾小時,等等。
還有一種計時方法就是直接使用today(今天)、tomorrow(明天)來指定完成命令的時間。下面通過一些例子來說明具體用法。
[例2] 指定在今天下午5:30執行某命令。假設現在時間是中午12:30,1999年2月24日,其命令格式如下:
at 5:30pm
at 17:30
at 17:30 today
at now + 5 hours
at now + 300 minutes
at 17:30 24.2.99
at 17:30 2/24/99
at 17:30 Feb 24
以上這些命令表達的意義是完全一樣的,所以在安排時間的時候完全可以根據個人喜好和具體情況自由選擇。一般採用絕對時間的24小時計時法可以避免由於用戶自己的疏忽造成計時錯誤的情況發生,例如上例可以寫成:
at 17:30 2/24/99
這樣非常清楚,而且別人也看得懂。
對於at命令來說,需要定時執行的命令是從標准輸入或者使用-f選項指定的文件中讀取並執行的。如果at命令是從一個使用su命令切換到用戶shell中執行的,那麼當前用戶被認為是執行用戶,所有的錯誤和輸出結果都會送給這個用戶。但是如果有郵件送出的話,收到郵件的將是原來的用戶,也就是登錄時shell的所有者。
[例3]
$ at -f work 4pm + 3 days
在三天後下午4點執行文件work中的作業。
$ at -f work 10am Jul 31
在7月31日上午10點執行文件work中的作業。
在任何情況下,超級用戶都可以使用這個命令。對於其他用戶來說,是否可以使用就取決於兩個文件:/etc/at.allow和/etc/at.deny。如果/etc/at.allow文件存在的話,那麼只有在其中列出的用戶才可以使用at命令;如果該文件不存在,那麼將檢查/etc/at.deny文件是否存在,在這個文件中列出的用戶均不能使用該命令。如果兩個文件都不存在,那麼只有超級用戶可以使用該命令;空的/etc/at.deny文件意味著所有的用戶都可以使用該命令,這也是默認狀態。
下面對命令中的參數進行說明。
-V 將標准版本號列印到標准錯誤中。
-q queue 使用指定的隊列。隊列名稱是由單個字母組成,合法的隊列名可以由a-z或者A-Z。a隊列是at命令的默認隊列。
-m 作業結束後發送郵件給執行at命令的用戶。
-f file 使用該選項將使命令從指定的file讀取,而不是從標准輸入讀取。
-l atq命令的一個別名。該命令用於查看安排的作業序列,它將列出用戶排在隊列中的作業,如果是超級用戶,則列出隊列中的所有工作。
命令的語法格式如下:
atq [-V] [-q 隊列] [-v]
-d atrm 命令的一個別名。該命令用於刪除指定要執行的命令序列,語法格式如下:
atrm [-V] 作業 [作業...]
-c 將命令行上所列的作業送到標准輸出。
[例4] 找出系統中所有以txt為後綴名的文件,並且進行列印。列印結束後給用戶foxy發出郵件通知取件。指定時間為十二月二十五日凌晨兩點。
首先鍵入:
$ at 2:00 12/25/99
然後系統出現at>提示符,等待用戶輸入進一步的信息,也就是需要執行的命令序列:
at> find / -name 「*.txt」|lpr
at> echo 「foxy:All texts have been printed.You can take them over.Good day!River」 |mail -s 」job done」 foxy
輸入完每一行指令然後回車,所有指令序列輸入完畢後,使用組合鍵結束at命令的輸入。這時候屏幕將出現如下信息:
warning:command will be executed using /bin/sh.
job 1 at 1999-12-25 02:00
提醒用戶將使用哪個shell來執行該命令序列。 實際上如果命令序列較長或者經常被執行的時候,一般都採用將該序列寫到一個文件中,然後將文件作為at命令的輸入來處理。這樣不容易出錯。
例5] 上面的例子可以修改如下:
將命令序列寫入到文件/tmp/printjob,語句為:
$ at -f /tmp/printjob 2:00 12/25/99
這樣一來,at命令將使用文件中的命令序列,屏幕顯示如下:
Warning:command will be executed using /bin/sh.
job 2 at 1999-12-25 02:00
當然也可以採用以下命令:
$ at< /tmp/printjob 2:00 12/25/99
來完成同樣的任務。也就是使用輸入重定向的辦法將文件定向為命令輸入。
batch命令
batch 用低優先順序運行作業,該命令幾乎和at命令的功能完全相同,唯一的區別在於,at命令是在指定時間,很精確的時刻執行指定命令;而batch卻是在系統負載較低,資源比較空閑的時候執行命令。該命令適合於執行佔用資源較多的命令。
batch命令的語法格式也和at命令十分相似,即
batch [-V] [-q 隊列] [-f 文件名] [-mv] [時間]
具體的參數解釋請參考at命令。一般地說,不用為batch命令指定時間參數,因為batch本身的特點就是由系統決定執行任務的時間,如果用戶再指定一個時間,就失去了本來的意義。
[例6] 使用例4,鍵入:
$ batch
at> find / -name *.txt|lpr
at> echo 「foxy:All texts have been printed.You can take them over.Good day!River」 |mail -s 」job done」 foxy
現在這個命令就會在合適的時間進行了,進行完後會發回一個信息。
仍然使用組合鍵來結束命令輸入。而且batch和at命令都將自動轉入後台,所以啟動的時候也不需要加上&符號。
cron命令
前面介紹的兩條命令都會在一定時間內完成一定任務,但是要注意它們都只能執行一次。也就是說,當指定了運行命令後,系統在指定時間完成任務,一切就結束了。但是在很多時候需要不斷重復一些命令,比如:某公司每周一自動向員工報告頭一周公司的活動情況,這時候就需要使用cron命令來完成任務了。
實際上,cron命令是不應該手工啟動的。cron命令在系統啟動時就由一個shell腳本自動啟動,進入後台(所以不需要使用&符號)。一般的用戶沒有運行該命令的許可權,雖然超級用戶可以手工啟動cron,不過還是建議將其放到shell腳本中由系統自行啟動。
首先cron命令會搜索/var/spool/cron目錄,尋找以/etc/passwd文件中的用戶名命名的crontab文件,被找到的這種文件將載入內存。例如一個用戶名為foxy的用戶,它所對應的crontab文件就應該是/var/spool/cron/foxy。也就是說,以該用戶命名的crontab文件存放在/var/spool/cron目錄下面。cron命令還將搜索/etc/crontab文件,這個文件是用不同的格式寫成的。
cron啟動以後,它將首先檢查是否有用戶設置了crontab文件,如果沒有就轉入「休眠」狀態,釋放系統資源。所以該後台進程佔用資源極少。它每分鍾「醒」過來一次,查看當前是否有需要運行的命令。命令執行結束後,任何輸出都將作為郵件發送給crontab的所有者,或者是/etc/crontab文件中MAILTO環境變數中指定的用戶。
上面簡單介紹了一些cron的工作原理,但是cron命令的執行不需要用戶干涉;需要用戶修改的是crontab中要執行的命令序列,所以下面介紹crontab命令。
crontab命令
crontab命令用於安裝、刪除或者列出用於驅動cron後台進程的表格。也就是說,用戶把需要執行的命令序列放到crontab文件中以獲得執行。每個用戶都可以有自己的crontab文件。下面就來看看如何創建一個crontab文件。
在/var/spool/cron下的crontab文件不可以直接創建或者直接修改。crontab文件是通過crontab命令得到的。現在假設有個用戶名為foxy,需要創建自己的一個crontab文件。首先可以使用任何文本編輯器建立一個新文件,然後向其中寫入需要運行的命令和要定期執行的時間。
然後存檔退出。假設該文件為/tmp/test.cron。再後就是使用crontab命令來安裝這個文件,使之成為該用戶的crontab文件。鍵入:
crontab test.cron
這樣一個crontab 文件就建立好了。可以轉到/var/spool/cron目錄下面查看,發現多了一個foxy文件。這個文件就是所需的crontab 文件。用more命令查看該文件的內容可以發現文件頭有三行信息:
#DO NOT EDIT THIS FILE -edit the master and reinstall.
#(test.cron installed on Mon Feb 22 14:20:20 1999)
#(cron version --$Id:crontab.c,v 2.13 1994/01/17 03:20:37 vivie Exp $)
大概意思是:
#切勿編輯此文件——如果需要改變請編輯源文件然後重新安裝。
#test.cron文件安裝時間:14:20:20 02/22/1999
如果需要改變其中的命令內容時,還是需要重新編輯原來的文件,然後再使用crontab命令安裝。
可以使用crontab命令的用戶是有限制的。如果/etc/cron.allow文件存在,那麼只有其中列出的用戶才能使用該命令;如果該文件不存在但cron.deny文件存在,那麼只有未列在該文件中的用戶才能使用crontab命令;如果兩個文件都不存在,那就取決於一些參數的設置,可能是只允許超級用戶使用該命令,也可能是所有用戶都可以使用該命令。
crontab命令的語法格式如下:
crontab [-u user] file
crontab [-u user]{-l|-r|-e}
第一種格式用於安裝一個新的crontab 文件,安裝來源就是file所指的文件,如果使用「-」符號作為文件名,那就意味著使用標准輸入作為安裝來源。
-u 如果使用該選項,也就是指定了是哪個具體用戶的crontab 文件將被修改。如果不指定該選項,crontab 將默認是操作者本人的crontab ,也就是執行該crontab 命令的用戶的crontab 文件將被修改。但是請注意,如果使用了su命令再使用crontab 命令很可能就會出現混亂的情況。所以如果是使用了su命令,最好使用-u選項來指定究竟是哪個用戶的crontab文件。
-l 在標准輸出上顯示當前的crontab。
-r 刪除當前的crontab文件。
-e 使用VISUAL或者EDITOR環境變數所指的編輯器編輯當前的crontab文件。當結束編輯離開時,編輯後的文件將自動安裝。
[例7]
# crontab -l #列出用戶目前的crontab。
10 6 * * * date
0 */2 * * * date
0 23-7/2,8 * * * date
#
在crontab文件中如何輸入需要執行的命令和時間。該文件中每行都包括六個域,其中前五個域是指定命令被執行的時間,最後一個域是要被執行的命令。每個域之間使用空格或者製表符分隔。格式如下:
minute hour day-of-month month-of-year day-of-week commands
第一項是分鍾,第二項是小時,第三項是一個月的第幾天,第四項是一年的第幾個月,第五項是一周的星期幾,第六項是要執行的命令。這些項都不能為空,必須填入。如果用戶不需要指定其中的幾項,那麼可以使用*代替。因為*是統配符,可以代替任何字元,所以就可以認為是任何時間,也就是該項被忽略了。在表4-1中給出了每項的合法范圍。
表4-1指定時間的合法范圍
時間
合法值
minute 00-59
hour 00-23,其中00點就是晚上12點
day-of-month
01-31
month-of-year
01-12
day-of-week
0-6,其中周日是0
這樣用戶就可以往crontab 文件中寫入無限多的行以完成無限多的命令。命令域中可以寫入所有可以在命令行寫入的命令和符號,其他所有時間域都支持列舉,也就是域中可以寫入很多的時間值,只要滿足這些時間值中的任何一個都執行命令,每兩個時間值中間使用逗號分隔。
[例8]
5,15,25,35,45,55 16,17,18 * * * command
這就是表示任意天任意月,其實就是每天的下午4點、5點、6點的5 min、15 min、25 min、35 min、45 min、55 min時執行命令。
[例9]
在每周一,三,五的下午3:00系統進入維護狀態,重新啟動系統。那麼在crontab 文件中就應該寫入如下欄位:
00 15 * * 1,3,5 shutdown -r +5
然後將該文件存檔為foxy.cron,再鍵入crontab foxy.cron安裝該文件。
[例10]
每小時的10分,40分執行用戶目錄下的innd/bbslin這個指令:
10,40 * * * * innd/bbslink
[例11]
每小時的1分執行用戶目錄下的bin/account這個指令:
1 * * * * bin/account
[例12]
每天早晨三點二十分執行用戶目錄下如下所示的兩個指令(每個指令以;分隔):
20 3 * * * (/bin/rm -f expire.ls logins.bad;bin/expire>expire.1st)
[例13]
每年的一月和四月,4號到9號的3點12分和3點55分執行/bin/rm -f expire.1st這個指令,並把結果添加在mm.txt這個文件之後(mm.txt文件位於用戶自己的目錄位置)。
12,55 3 4-9 1,4 * /bin/rm -f expire.1st>> m.txt
[例14]
我們來看一個超級用戶的crontab文件:
#Run the 『atrun』 program every minutes
#This runs anything that』s e to run from 『at』.See man 『at』 or 『atrun』. 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/lib/atrun
40 7 * * * updatedb
8,10,22,30,39,46,54,58 * * * * /bin/sync
進程的掛起及恢復命令bg、fg
作業控制允許將進程掛起並可以在需要時恢復進程的運行,被掛起的作業恢復後將從中止處開始繼續運行。只要在鍵盤上按,即可掛起當前的前台作業。
[例15]
$ cat >
< ctrl+z>
text.file [1] + stopped cat > text.file
$ jobs [1]+ stopped cat >text.file
在鍵盤上按後,將掛起當前執行的命令cat。使用jobs命令可以顯示shell的作業清單,包括具體的作業、作業號以及作業當前所處的狀態。
恢復進程執行時,有兩種選擇:用fg命令將掛起的作業放回到前台執行;用bg命令將掛起的作業放到後台執行。
[例16]
用戶正在使用Emacs,突然需要查看系統進程情況。就首先使用組合鍵將Emacs進程掛起,然後使用bg命令將其在後台啟動,這樣就得到了前台的操作控制權,接著鍵入「ps –x」查看進程情況。查看完畢後,使用fg命令將Emacs帶回前台運行即可。其命令格式為:
< ctrl+z>
$ bg emacs
$ ps –x
$ fg emacs
默認情況下,fg和bg命令對最近停止的作業進行操作。如果希望恢復其他作業的運行,可以在命令中指定要恢復作業的作業號來恢復該作業。例如:
$ fg 1
cat > text.file
靈活使用上述命令,將給自己帶來很大的方便。

⑵ Linux系統開機時啟動內核步驟是什麼

實模式,並開始執行位於地址0xFFFF0處
的代碼,也就是ROM-BIOS起始位置的代碼。BIOS先進行一系列的系統自檢,然後初始化位
於地址0的中斷向量表。最後BIOS將啟動盤的第一個扇區裝入到0x7C00,並開始執行此處
的代碼。這就是對內核初始化過程的一個最簡單的描述。
最初,linux核心的最開始部分是用8086匯編語言編寫的。當開始運行時,核心將自
己裝入到絕對地址0x90000,再將其後的2k位元組裝入到地址0x90200處,最後將核心的其餘
部分裝入到0x10000。
當系統裝入時,會顯示Loading...信息。裝入完成後,控制轉向另一個實模式下的匯
編語言代碼boot/Setup.S。Setup部分首先設置一些系統的硬體設備,然後將核心從
0x10000處移至0x1000處。這時系統轉入保護模式,開始執行位於0x1000處的代碼。
接下來是內核的解壓縮。0x1000處的代碼來自於文件Boot/head.S,它用來初始化寄
存器和調用decompress_kernel( )程序。decompress_kernel( )程序由Boot/inflate.c,
Boot/unzip.c和Boot../misc.c組成。解壓縮後的數據被裝入到了0x100000處,這也是
linux不能在內存小於2M的環境下運行的主要原因。
解壓後的代碼在0x1010000處開始執行,緊接著所有的32位的設置都將完成: IDT、
GDT和LDT將被裝入,處理器初始化完畢,設置好內存頁面,最終調用start_kernel過程。
這大概是整個內核中最為復雜的部分。
[系統開始運行]
linux kernel 最早的C代碼從匯編標記startup_32開始執行
startup_32:
start_kernel
lock_kernel
trap_init
init_IRQ
sched_init
softirq_init
time_init
console_init
#ifdef CONFIG_MODULES
init_moles
#endif
kmem_cache_init
sti
calibrate_delay
mem_init
kmem_cache_sizes_init
pgtable_cache_init
fork_init
proc_caches_init
vfs_caches_init
buffer_init
page_cache_init
signals_init
#ifdef CONFIG_PROC_FS
proc_root_init
#endif
#if defined(CONFIG_SYSVIPC)
ipc_init
#endif
check_bugs
smp_init
rest_init
kernel_thread
unlock_kernel
cpu_idle
・startup_32 [arch/i386/kernel/head.S]
・start_kernel [init/main.c]
・lock_kernel [include/asm/smplock.h]
・trap_init [arch/i386/kernel/traps.c]
・init_IRQ [arch/i386/kernel/i8259.c]
・sched_init [kernel/sched.c]
・softirq_init [kernel/softirq.c]
・time_init [arch/i386/kernel/time.c]
・console_init [drivers/char/tty_io.c]
・init_moles [kernel/mole.c]
・kmem_cache_init [mm/slab.c]
・sti [include/asm/system.h]
・calibrate_delay [init/main.c]
・mem_init [arch/i386/mm/init.c]
・kmem_cache_sizes_init [mm/slab.c]
・pgtable_cache_init [arch/i386/mm/init.c]
・fork_init [kernel/fork.c]
・proc_caches_init
・vfs_caches_init [fs/dcache.c]
・buffer_init [fs/buffer.c]
・page_cache_init [mm/filemap.c]
・signals_init [kernel/signal.c]
・proc_root_init [fs/proc/root.c]
・ipc_init [ipc/util.c]
・check_bugs [include/asm/bugs.h]
・smp_init [init/main.c]
・rest_init
・kernel_thread [arch/i386/kernel/process.c]
・unlock_kernel [include/asm/smplock.h]
・cpu_idle [arch/i386/kernel/process.c]
start_kernel( )程序用於初始化系統內核的各個部分,包括:
*設置內存邊界,調用paging_init( )初始化內存頁面。
*初始化陷阱,中斷通道和調度。
*對命令行進行語法分析。
*初始化設備驅動程序和磁碟緩沖區。
*校對延遲循環。
最後的function'rest_init' 作了以下工作:
・開辟內核線程'init'
・調用unlock_kernel
・建立內核運行的cpu_idle環, 如果沒有調度,就一直死循環
實際上start_kernel永遠不能終止.它會無窮地循環執行cpu_idle.
最後,系統核心轉向move_to_user_mode( ),以便創建初始化進程(init)。此後,進程0開始進入無限循環。
初始化進程開始執行/etc/init、/bin/init 或/sbin /init中的一個之後,系統內核就不再對程序進行直接控制了。之後系統內核的作用主要是給進程提供系統調用,以及提供非同步中斷事件的處理。多任務機制已經建立起來,並開始處理多個用戶的登錄和fork( )創建的進程。
[init]
init是第一個進程,或者說內核線程
init
lock_kernel
do_basic_setup
mtrr_init
sysctl_init
pci_init
sock_init
start_context_thread
do_init_calls
(*call())-> kswapd_init
prepare_namespace
free_initmem
unlock_kernel
execve
[目錄]
--------------------------------------------------------------------------------
啟動步驟
系統引導:
涉及的文件
./arch/$ARCH/boot/bootsect.s
./arch/$ARCH/boot/setup.s
bootsect.S
這個程序是linux kernel的第一個程序,包括了linux自己的bootstrap程序,
但是在說明這個程序前,必須先說明一般IBM PC開機時的動作(此處的開機是指
"打開PC的電源"):
一般PC在電源一開時,是由內存中地址FFFF:0000開始執行(這個地址一定
在ROM BIOS中,ROM BIOS一般是在FEOOOh到FFFFFh中),而此處的內容則是一個
jump指令,jump到另一個位於ROM BIOS中的位置,開始執行一系列的動作,包
括了檢查RAM,keyboard,顯示器,軟硬磁碟等等,這些動作是由系統測試代碼
(system test code)來執行的,隨著製作BIOS廠商的不同而會有些許差異,但都
是大同小異,讀者可自行觀察自家機器開機時,螢幕上所顯示的檢查訊息。
緊接著系統測試碼之後,控制權會轉移給ROM中的啟動程序
(ROM bootstrap routine),這個程序會將磁碟上的第零軌第零扇區讀入
內存中(這就是一般所謂的boot sector,如果你曾接觸過電腦病
毒,就大概聽過它的大名),至於被讀到內存的哪裡呢? --絕對
位置07C0:0000(即07C00h處),這是IBM系列PC的特性。而位在linux開機
磁碟的boot sector上的正是linux的bootsect程序,也就是說,bootsect是
第一個被讀入內存中並執行的程序。現在,我們可以開始來
看看到底bootsect做了什麼。
第一步
首先,bootsect將它"自己"從被ROM BIOS載入的絕對地址0x7C00處搬到
0x90000處,然後利用一個jmpi(jump indirectly)的指令,跳到新位置的
jmpi的下一行去執行,
第二步
接著,將其他segment registers包括DS,ES,SS都指向0x9000這個位置,
與CS看齊。另外將SP及DX指向一任意位移地址( offset ),這個地址等一下
會用來存放磁碟參數表(disk para- meter table )
第三步
接著利用BIOS中斷服務int 13h的第0號功能,重置磁碟控制器,使得剛才
的設定發揮功能。
第四步
完成重置磁碟控制器之後,bootsect就從磁碟上讀入緊鄰著bootsect的setup
程序,也就是setup.S,此讀入動作是利用BIOS中斷服務int 13h的第2號功能。
setup的image將會讀入至程序所指定的內存絕對地址0x90200處,也就是在內存
中緊鄰著bootsect 所在的位置。待setup的image讀入內存後,利用BIOS中斷服
務int 13h的第8號功能讀取目前磁碟的參數。
第五步
再來,就要讀入真正linux的kernel了,也就是你可以在linux的根目錄下看
到的"vmlinuz" 。在讀入前,將會先呼叫BIOS中斷服務int 10h 的第3號功能,
讀取游標位置,之後再呼叫BIOS 中斷服務int 10h的第13h號功能,在螢幕上輸
出字串"Loading",這個字串在boot linux時都會首先被看到,相信大家應該覺
得很眼熟吧。
第六步
接下來做的事是檢查root device,之後就仿照一開始的方法,利用indirect
jump 跳至剛剛已讀入的setup部份
第七步
setup.S完成在實模式下版本檢查,並將硬碟,滑鼠,內存參數寫入到 INITSEG
中,並負責進入保護模式。
第八步
操作系統的初始化。

⑶ Linux服務開機自啟動三種方式,你覺得哪種最優雅

很多時候,我們需要將一些服務在Linux系統啟動時即自動運行,省得每次都要去手動啟動一遍,如Redis, MySQL, Nginx等。本文對CentOS與Ubuntu下開機自啟動的配置方法進行整理,供參考查閱。

rc.local是CentOS以前版本的方式,在CentOS7中仍然以兼容的形式存在,雖仍可用,但不推薦(推薦使用systemd service)。

1、編寫需要開機自啟動的腳本,並添加執行許可權

作為測試,上述腳本列印一個時間到/tmp/test.log文件中

2、在/etc/rc.d/rc.local配置文件中添加腳本運行命令(使用絕對路徑)

3、添加/etc/rc.d/rc.local文件的執行許可權

在centos7中,/etc/rc.d/滾毀岩rc.local沒有執行許可權,需要手動授權

以上三步,即可使/root/test_rclocal.sh >/dev/null 2>/dev/null 命令在伺服器系統啟動時自動運行。

1、編寫需要開機自啟動的測試腳本,並添加執行許可權

2、在/etc/rc.d/init.d/目錄下添加一個可執行腳本testchkconfig

上述testchkconfig腳本的頭部必須遵循一定的格式 # chkconfig: 2345 90 10, 其中2345指定服務在哪些執行等級中開啟或關閉,90表示啟動的優先順序(0-100,越大優先順序越低),10表示關閉的優先順序。執行等級包括

3、加入開機啟動服務列表

使用 chkconfig --list 可查看當前加入開機自啟動的服務列表,但如Note部分所述,該命令只顯示SysV服務,不包含原生的systemd服務,查看systemd服務可使用systemctl list-unit-files命令。

以上三步,即可使/root/test_chkconfig.sh >/dev/null 2>/dev/null 命令在伺服器系統啟動時自動運行。

chkconfig的其它命令參考

CentOS7的余滾systemd服務腳本存放在:/usr/lib/systemd/system(系統級)/usr/lib/systemd/user(用戶級)下,以.service結尾。這里以nginx為例

1、在/usr/lib/systemd/system目錄大御下創建nginx.service文件

其中Service部分的Type包括如下幾種類型:

2、 開啟開機自啟動

以上兩步,就將nginx服務配置成了在操作系統啟動時自動啟動。

其它命令參考

從字面看是PID文件不可讀,查看/var/run/nginx.pid,該文件也確實不存在,查看nginx.conf配置文件,發現是pid /var/run/nginx.pid;這行配置被注釋掉了, 如果不指定pid文件位置,nginx默認會把pid文件保存在logs目錄中。所以出現systemd啟動服務時找不到pid文件而報錯,將nginx.conf中的pid配置注釋去掉,重啟nginx.service即可。

在Ubuntu18.04中,主要也是以systemd服務來實現開機自啟動,systemd默認讀取/etc/systemd/system/下的配置文件,該目錄下的一些文件會鏈接到/lib/systemd/system/下的文件。

因此可以在/etc/systemd/system/目錄下面創建一個自啟動服務配置,以內網穿透服務frp客戶端為例,如

各配置項與CentOS類似。然後將伺服器加到自啟動列表中並啟動服務

其它更多systemctl命令與CentOS類似。

也可以使用/lib/systemd/system/rc-local.service來執行一些開機需要執行的腳本,該文件內容為

從Description看它是為了兼容之前版本的/etc/rc.local的,該服務啟動命名就是/etc/rc.local start,將該文件鏈接到/etc/systemd/system下

創建/etc/rc.local文件,並賦予可執行許可權

作者:半路雨歌
鏈接:https://juejin.cn/post/6844904104515338248

⑷ Linux驅動程序的工作原理

由於你的問題太長我只好轉載別人的手打的太累不好意思~~~
Linux是Unix***作系統的一種變種,在Linux下編寫驅動程序的原理和

思想完全類似於其他的Unix系統,但它dos或window環境下的驅動程序有很大的

區別.在Linux環境下設計驅動程序,思想簡潔,***作方便,功芤埠芮看?但是

支持函數少,只能依賴kernel中的函數,有些常用的***作要自己來編寫,而且調

試也不方便.本人這幾周來為實驗室自行研製的一塊多媒體卡編制了驅動程序,

獲得了一些經驗,願與Linux fans共享,有不當之處,請予指正.

以下的一些文字主要來源於khg,johnsonm的Write linux device driver,

Brennan's Guide to Inline Assembly,The Linux A-Z,還有清華BBS上的有關

device driver的一些資料. 這些資料有的已經過時,有的還有一些錯誤,我依

據自己的試驗結果進行了修正.

一. Linux device driver 的概念

系統調用是***作系統內核和應用程序之間的介面,設備驅動程序是***作系統

內核和機器硬體之間的介面.設備驅動程序為應用程序屏蔽了硬體的細節,這樣

在應用程序看來,硬體設備只是一個設備文件, 應用程序可以象***作普通文件

一樣對硬體設備進行***作.設備驅動程序是內核的一部分,它完成以下的功能:

1.對設備初始化和釋放.

2.把數據從內核傳送到硬體和從硬體讀取數據.

3.讀取應用程序傳送給設備文件的數據和回送應用程序請求的數據.

4.檢測和處理設備出現的錯誤.

在Linux***作系統下有兩類主要的設備文件類型,一種是字元設備,另一種是

塊設備.字元設備和塊設備的主要區別是:在對字元設備發出讀/寫請求時,實際

的硬體I/O一般就緊接著發生了,塊設備則不然,它利用一塊系統內存作緩沖區,

當用戶進程對設備請求能滿足用戶的要求,就返回請求的數據,如果不能,就調用請求函數來進行實際

的I/O***作.塊設備是主要針對磁碟等慢速設備設計的,以免耗費過多的CPU時間

來等待.

已經提到,用戶進程是通過設備文件來與實際的硬體打交道.每個設備文件都

都有其文件屬性(c/b),表示是字元設備還蔤強檣璞?另外每個文件都有兩個設

備號,第一個是主設備號,標識驅動程序,第二個是從設備號,標識使用同一個

設備驅動程序的不同的硬體設備,比如有兩個軟盤,就可以用從設備號來區分

他們.設備文件的的主設備號必須與設備驅動程序在登記時申請的主設備號

一致,否則用戶進程將無法訪問到驅動程序.

最後必須提到的是,在用戶進程調用驅動程序時,系統進入核心態,這時不再是

搶先式調度.也就是說,系統必須在你的驅動程序的子函數返回後才能進行其他

的工作.如果你的驅動程序陷入死循環,不幸的是你只有重新啟動機器了,然後就

是漫長的fsck.//hehe

(請看下節,實例剖析)

讀/寫時,它首先察看緩沖區的內容,如果緩沖區的數據

如何編寫Linux***作系統下的設備驅動程序

Roy G

二.實例剖析

我們來寫一個最簡單的字元設備驅動程序.雖然它什麼也不做,但是通過它

可以了解Linux的設備驅動程序的工作原理.把下面的C代碼輸入機器,你就會

獲得一個真正的設備驅動程序.不過我的kernel是2.0.34,在低版本的kernel

上可能會出現問題,我還沒測試過.//xixi

#define __NO_VERSION__

#include

#include

char kernel_version [] = UTS_RELEASE;

這一段定義了一些版本信息,雖然用處不是很大,但也必不可少.Johnsonm說所

有的驅動程序的開頭都要包含,但我看倒是未必.

由於用戶進程是通過設備文件同硬體打交道,對設備文件的***作方式不外乎就

是一些系統調用,如 open,read,write,close...., 注意,不是fopen, fread.,

但是如何把系統調用和驅動程序關聯起來呢?這需要了解一個非常關鍵的數據

結構:

struct file_operations {

int (*seek) (struct inode * ,struct file *, off_t ,int);

int (*read) (struct inode * ,struct file *, char ,int);

int (*write) (struct inode * ,struct file *, off_t ,int);

int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);

int (*select) (struct inode * ,struct file *, int ,select_table *);

int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long

int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);

int (*open) (struct inode * ,struct file *);

int (*release) (struct inode * ,struct file *);

int (*fsync) (struct inode * ,struct file *);

int (*fasync) (struct inode * ,struct file *,int);

int (*check_media_change) (struct inode * ,struct file *);

int (*revalidate) (dev_t dev);

}

這個結構的每一個成員的名字都對應著一個系統調用.用戶進程利用系統調用

在對設備文件進行諸如read/write***作時,系統調用通過設備文件的主設備號

找到相應的設備驅動程序,然後讀取這個數據結構相應的函數指針,接著把控制

權交給該函數.這是linux的設備驅動程序工作的基本原理.既然是這樣,則編寫

設備驅動程序的主要工作就是編寫子函數,並填充file_operations的各個域.

相當簡單,不是嗎?

下面就開始寫子程序.

#include

#include

#include

#include

#include

unsigned int test_major = 0;

static int read_test(struct inode *node,struct file *file,

char *buf,int count)

{

int left;

if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )

return -EFAULT;

for(left = count left > 0 left--)

{

__put_user(1,buf,1);

buf++;

}

return count;

}

這個函數是為read調用准備的.當調用read時,read_test()被調用,它把用戶的

緩沖區全部寫1.

buf 是read調用的一個參數.它是用戶進程空間的一個地址.但是在read_test

被調用時,系統進入核心態.所以不能使用buf這個地址,必須用__put_user(),

這是kernel提供的一個函數,用於向用戶傳送數據.另外還有很多類似功能的

函數.請參考.在向用戶空間拷貝數據之前,必須驗證buf是否可用.

這就用到函數verify_area.

static int write_tibet(struct inode *inode,struct file *file,

const char *buf,int count)

{

return count;

}

static int open_tibet(struct inode *inode,struct file *file )

{

MOD_INC_USE_COUNT;

return 0;

} static void release_tibet(struct inode *inode,struct file *file )

{

MOD_DEC_USE_COUNT;

}

這幾個函數都是空***作.實際調用發生時什麼也不做,他們僅僅為下面的結構

提供函數指針。

struct file_operations test_fops = {

NULL,

read_test,

write_test,

NULL, /* test_readdir */

NULL,

NULL, /* test_ioctl */

NULL, /* test_mmap */

open_test,

release_test, NULL, /* test_fsync */

NULL, /* test_fasync */

/* nothing more, fill with NULLs */

};

設備驅動程序的主體可以說是寫好了。現在要把驅動程序嵌入內核。驅動程序

可以按照兩種方式編譯。一種是編譯進kernel,另一種是編譯成模塊(moles),

如果編譯進內核的話,會增加內核的大小,還要改動內核的源文件,而且不能

動態的卸載,不利於調試,所以推薦使用模塊方式。

int init_mole(void)

{

int result;

result = register_chrdev(0, "test", &test_fops);

if (result < 0) {

printk(KERN_INFO "test: can't get major number ");

return result;

}

if (test_major == 0) test_major = result; /* dynamic */

return 0;

}

在用insmod命令將編譯好的模塊調入內存時,init_mole 函數被調用。在

這里,init_mole只做了一件事,就是向系統的字元設備表登記了一個字元

設備。register_chrdev需要三個參數,參數一是希望獲得的設備號,如果是

零的話,系統將選擇一個沒有被佔用的設備號返回。參數二是設備文件名,

參數三用來登記驅動程序實際執行***作的函數的指針。

如果登記成功,返回設備的主設備號,不成功,返回一個負值。

void cleanup_mole(void)

{

unregister_chrdev(test_major, "test");

}

在用rmmod卸載模塊時,cleanup_mole函數被調用,它釋放字元設備test

在系統字元設備表中佔有的表項。

一個極其簡單的字元設備可以說寫好了,文件名就叫test.c吧。

下面編譯

$ gcc -O2 -DMODULE -D__KERNEL__ -c test.c

得到文件test.o就是一個設備驅動程序。

如果設備驅動程序有多個文件,把每個文件按上面的命令行編譯,然後

ld -r file1.o file2.o -o molename.

驅動程序已經編譯好了,現在把它安裝到系統中去。

$ insmod -f test.o

如果安裝成功,在/proc/devices文件中就可以看到設備test,

並可以看到它的主設備號,。

要卸載的話,運行

$ rmmod test

下一步要創建設備文件。

mknod /dev/test c major minor

c 是指字元設備,major是主設備號,就是在/proc/devices里看到的。

用shell命令

$ cat /proc/devices | awk "\$2=="test" {print \$1}"

就可以獲得主設備號,可以把上面的命令行加入你的shell script中去。

minor是從設備號,設置成0就可以了。

我們現在可以通過設備文件來訪問我們的驅動程序。寫一個小小的測試程序。

#include

#include

#include

#include

main()

{

int testdev;

int i;

char buf[10];

testdev = open("/dev/test",O_RDWR);

if ( testdev == -1 )

{

printf("Cann't open file ");

exit(0);

}

read(testdev,buf,10);

for (i = 0; i < 10;i++)

printf("%d ",buf);

close(testdev);

}

編譯運行,看看是不是列印出全1 ?

以上只是一個簡單的演示。真正實用的驅動程序要復雜的多,要處理如中斷,

DMA,I/O port等問題。這些才是真正的難點。請看下節,實際情況的處理。

如何編寫Linux***作系統下的設備驅動程序

Roy G

三 設備驅動程序中的一些具體問題。

1. I/O Port.

和硬體打交道離不開I/O Port,老的ISA設備經常是佔用實際的I/O埠,

在linux下,***作系統沒有對I/O口屏蔽,也就是說,任何驅動程序都可以

對任意的I/O口***作,這樣就很容易引起混亂。每個驅動程序應該自己避免

誤用埠。

有兩個重要的kernel函數可以保證驅動程序做到這一點。

1)check_region(int io_port, int off_set)

這個函數察看系統的I/O表,看是否有別的驅動程序佔用某一段I/O口。

參數1:io埠的基地址,

參數2:io埠佔用的范圍。

返回值:0 沒有佔用, 非0,已經被佔用。

2)request_region(int io_port, int off_set,char *devname)

如果這段I/O埠沒有被佔用,在我們的驅動程序中就可以使用它。在使用

之前,必須向系統登記,以防止被其他程序佔用。登記後,在/proc/ioports

文件中可以看到你登記的io口。

參數1:io埠的基地址。

參數2:io埠佔用的范圍。

參數3:使用這段io地址的設備名。

在對I/O口登記後,就可以放心地用inb(), outb()之類的函來訪問了。

在一些pci設備中,I/O埠被映射到一段內存中去,要訪問這些埠就相當

於訪問一段內存。經常性的,我們要獲得一塊內存的物理地址。在dos環境下,

(之所以不說是dos***作系統是因為我認為DOS根本就不是一個***作系統,它實

在是太簡單,太不安全了)只要用段:偏移就可以了。在window95中,95ddk

提供了一個vmm 調用 _MapLinearToPhys,用以把線性地址轉化為物理地址。但

在Linux中是怎樣做的呢?

2 內存***作

在設備驅動程序中動態開辟內存,不是用malloc,而是kmalloc,或者用

get_free_pages直接申請頁。釋放內存用的是kfree,或free_pages. 請注意,

kmalloc等函數返回的是物理地址!而malloc等返回的是線性地址!關於

kmalloc返回的是物理地址這一點本人有點不太明白:既然從線性地址到物理

地址的轉換是由386cpu硬體完成的,那樣匯編指令的***作數應該是線性地址,

驅動程序同樣也不能直接使用物理地址而是線性地址。但是事實上kmalloc

返回的確實是物理地址,而且也可以直接通過它訪問實際的RAM,我想這樣可

以由兩種解釋,一種是在核心態禁止分頁,但是這好像不太現實;另一種是

linux的頁目錄和頁表項設計得正好使得物理地址等同於線性地址。我的想法

不知對不對,還請高手指教。

言歸正傳,要注意kmalloc最大隻能開辟128k-16,16個位元組是被頁描述符

結構佔用了。kmalloc用法參見khg.

內存映射的I/O口,寄存器或者是硬體設備的RAM(如顯存)一般佔用F0000000

以上的地址空間。在驅動程序中不能直接訪問,要通過kernel函數vremap獲得

重新映射以後的地址。

另外,很多硬體需要一塊比較大的連續內存用作DMA傳送。這塊內存需要一直

駐留在內存,不能被交換到文件中去。但是kmalloc最多隻能開辟128k的內存。

這可以通過犧牲一些系統內存的方法來解決。

具體做法是:比如說你的機器由32M的內存,在lilo.conf的啟動參數中加上

mem=30M,這樣linux就認為你的機器只有30M的內存,剩下的2M內存在vremap

之後就可以為DMA所用了。

請記住,用vremap映射後的內存,不用時應用unremap釋放,否則會浪費頁表。

3 中斷處理

同處理I/O埠一樣,要使用一個中斷,必須先向系統登記。

int request_irq(unsigned int irq ,

void(*handle)(int,void *,struct pt_regs *),

unsigned int long flags,

const char *device);

irq: 是要申請的中斷。

handle:中斷處理函數指針。

flags:SA_INTERRUPT 請求一個快速中斷,0 正常中斷。

device:設備名。

如果登記成功,返回0,這時在/proc/interrupts文件中可以看你請求的

中斷。

4一些常見的問題。

對硬體***作,有時時序很重要。但是如果用C語言寫一些低級的硬體***作

的話,gcc往往會對你的程序進行優化,這樣時序就錯掉了。如果用匯編寫呢,

gcc同樣會對匯編代碼進行優化,除非你用volatile關鍵字修飾。最保險的

辦法是禁止優化。這當然只能對一部分你自己編寫的代碼。如果對所有的代碼

都不優化,你會發現驅動程序根本無法裝載。這是因為在編譯驅動程序時要

用到gcc的一些擴展特性,而這些擴展特性必須在加了優化選項之後才能體現

出來。

關於kernel的調試工具,我現在還沒有發現有合適的。有誰知道請告訴我,

不勝感激。我一直都在printk列印調試信息,倒也還湊合。

關於設備驅動程序還有很多內容,如等待/喚醒機制,塊設備的編寫等。

我還不是很明白,不敢亂說。

⑸ 安裝linux系統實驗原理

1) 啟動vmware虛擬機
2) 單擊「文件—>新建?虛擬機」,出現「安裝虛擬機向導」對話框,單擊「下一步」,選「典型」;
3)「客戶機操作系統」選擇安裝linux,版本選「redhat linux」,單擊「下一步」;
4) 在「虛擬機名稱」處:輸入「linux」, 創建指定位置(不要選擇在c盤)的磁碟映像文件linux.vmx單擊「下一步」,出現「網路連接」 設置界面,選擇「使用橋接網路」 單擊下一步;
5) 磁碟容量為8g, 單擊「完成」;
6)編輯虛擬機設置:
雙擊設備欄「cd-rom」,選擇「使用iso鏡像」;指定鏡像文件路徑,例如: d:\redhatlinux_isofiles\redhatlinux9_i386_disc1.iso ;
floppy設備欄取消「打開電源時連接「
7) 配置步驟完成,啟動系統。

⑹ linux 管道原理

Linux原理的學習,我打算由淺入深,從上之下,也就是先了解個大概再逐個深入。先了解一下Linux的進程先。

一、Linux進程上下文

Linux進程上下文,我理解就是進程組成元素的集合。包括進程描述符tast_struct,正文段,數據段,棧,寄存器內容,頁表等。

1)tast_struct

它是一種數據結構,存儲著進程的描述信息,例如pid,uid,狀態,信號項,打開文件表等。是進程管理和調度的重要依據。

2)用戶棧和核心棧

顧名思義,用戶棧是進程運行在用戶態使用的棧,含有用戶態執行時候函數調用的參數,局部變數等;核心棧是該進程運行在核心態下用的棧,保存調用系統函數所用的參數和調用序列。這兩個棧的指針都保存在tast_struct結構中。

3)寄存器

保存程序計數器,狀態字,通用寄存器,棧指針。

4)頁表

線性地址到物理地址的映射

5)正文段,數據段。

二、Linux進程的狀態

Linux中進程共有5個狀態:就緒,可中斷睡眠,不可中斷睡眠,暫停,僵死。也就是說,linux不區分就緒和運行,它們統一叫做就緒態。進程所處的狀態記錄在tast_struct中。

三、進程的控制

1)進程樹的形成

計算機啟動後,BIOS從磁碟引導扇區載入系統引導程序,它將Linux系統裝入內存,並跳到內核處執行,Linux內核就執行初始化工作:初始化硬體、初始化內部數據結構、建立進程0。進程0創建進程1,進程1是以後所有創建的進程的祖先,它負責初始化所有的用戶進程。進程1創建shell進程,shell進程顯示提示符,等待命令的輸入。

2)進程的創建

任何一個用戶進程的創建都是由現有的一個進程完成的,進程的創建要經過fork和exec兩個過程。Fork是為新進程分配相應的數據結構,並將父進程的相應上下文信息復制過來。Exec是將可執行文件的正文和數據轉入內存覆蓋它原來的(從父進程復制過來的),並開始執行正文段。

3)進程的終止

系統調用exit()就可自我終結,exit釋放除了tast_struct以外的所有上下文,父進程收到子進程終結的消息後,釋放子進程的tast_struct。

4)進程的調度

進程的調度是由schele()完成的,一種情況是,當處理機從核心態向用戶態轉換之前,它會檢查調度標志是否為1,如果是1,則運行schele(),執行進程的調度。另一種情況是進程自動放棄處理機,時候進行進程調度。

進程的調度過程分為兩步,首先利用相關策略選擇要執行的進程,然後進行上下文的切換。

四、進程的通信

進程的通信策略主要有,消息,管道,消息隊列,共享存儲區和信號量。

1)信息

消息機制主要是用來傳遞進程間的軟中斷信號,通知對方發生了非同步事件。發送進程將信號(約定好的符號)發送到目標進程的tast_struct中的信號項,接收進程看到有消息後就調用相應的處理程序,注意,處理程序必須到進程執行時候才能執行,不能立即響應。

2)管道

我理解就是兩個進程使用告訴緩沖區中的一個隊列(每兩個進程一個),發送進程將數據發送到管道入口,接收進程從管道出口讀數據。

3) 消息隊列

消息隊列是操作系統維護的一個個消息鏈表,發送進程根據消息標識符將消息添加到制定隊列中,接收進程從中讀取消息。

4)共享存儲區

在內存中開辟一個區域,是個進程共享的,也就是說進程可以把它附加到自己的地址空間中,對此區域中的數據進行操作。

5)信號量

控制進程的同步。

⑺ Linux系統啟動的大致過程

Linux系統啟動的大致過程

Linux操作系統是基於UNIX操作系統發展而來的一種克隆系統,它誕生於1991 年的 [Linux桌面] 10 月5 日。下面我准備了關於Linux系統啟動的大致過程,提供給大家參考!

第一階段:BIOS啟動引導階段;

在該過程中實現硬體的.初始化以及查找啟動介質;

從MBR中裝載啟動引導管理器(GRUB)並運行該啟動引導管理

第二階段:GRUB啟動引導階段;

裝載stage1

裝載stage1.5

裝載stage2

讀取/boot/grub.conf文件並顯示啟動菜單;

裝載所選的kernel和initrd文件到內存中

第三階段:內核階段:

運行內核啟動參數;

解壓initrd文件並掛載initd文件系統,裝載必須的驅動;

掛載根文件系統

第四階段:Sys V init初始化階段:

啟動/sbin/init程序;

運行rc.sysinit腳本,設置系統環境,啟動swap分區,檢查和掛載文件系統;

讀取/etc/inittab文件,運行在/et/rc.d/rc<#>.d中定慶液義的不同運行級別的服務初始化腳本;

打開字清差睜符終端1-6號控制台/打開圖形顯示管理的7號控制台

同時在上述過程中各階段所需要讀取的文件和操作的對象:

BIOS啟動引導階段 GRUB啟答歲動引導階段 內核階段 /init/sysinit階段

====================================================================================

None /boot/grub/grub.conf /boot/vmlinuz- /etc/rc.d/rc.sysinit

/boot/grub/stage1_5 /boot/initrd- /etc/inittab

/boot/grub/stage2 /etc/rc.d/rc<#>.d

/etc/rc.d/init.d/*

;

⑻ Linux( bootloader)啟動操作系統過程

Linux Booting Process:
(1) BIOS
功能:執行計算機系統完整性檢測;通電自檢;搜索/載入/執行 boot loader程序。
一旦 boot loader 程序被探測到,並且載入到內存,BIOS會把控制權交給它。
(2) MBR
MBR位於引導盤(Bootable Disk)的第一個扇區(512B)。
通常是在 /dev/sda 或者 /dev/hda 。

注意:引導盤(bootable disk)和引導分區(bootable partition)的區別。

(3) GRUB
GRUB = Grand Unified Bootloader

如果在系統中安裝有多個內核鏡像,你可以選擇某一個被執行。
GRUB展示了一個啟動畫面,等待幾秒,如果你不輸入任何字元,它將會按照grub配置文件的規定載入默認的內核鏡像。

Grub配置文件在: /boot/grub/grub.conf
它包含了內核和initrd.img

(4) Kernal
(注意Kernal和kernel不一樣)

Kernal按照grub.conf文件的規定,掛載根文件系統。
一旦kernal啟動,它第一件事情就是執行:sbin/init 進程。

initrd是被kernel用做臨時根文件系統,直到Kernal掛載了根文件系統。

(5) INIT(Initilization)

根據 /etc/inittab 文件決定Linux運行層級,運行級別決定了哪個初始化程序(Initial Programs)被載入到啟動項。

(6) Run Level

根據你的運行級別的設定,操作系統會執行下來對應的文件夾下的程序:

Linux的7個運行級別(Run levels):

標準的Linux運行級別為3或者5,如果是3的話,系統就在多用戶狀態;如果是5的話,則是運行著XWindow系統。不同的運行級別有著不同的用處,也應該根據自己的不同清晰來設置。例如,如果丟失了root口令,那麼可以讓機器啟動進入單用戶模式來設置。

如果是使用S(Start)開頭的程序,那麼是用在啟動的時候,
如果是使用K(Kill)開頭的程序,那麼是用在關機的時候。

閱讀全文

與linux啟動原理相關的資料

熱點內容
linux文件操作命令 瀏覽:125
安卓手機圖片文件夾加鎖 瀏覽:778
steam提示音在哪個文件夾 瀏覽:337
項目開發全程實錄pdf 瀏覽:530
單片機reset 瀏覽:595
pdf怎麼是英文 瀏覽:969
旗雲2壓縮機保險 瀏覽:374
做程序員壓力大嗎表情包 瀏覽:312
pdf下拉 瀏覽:371
php去掉小數後面的0 瀏覽:954
阿里備案買什麼伺服器 瀏覽:261
網路驅動下載到哪個文件夾 瀏覽:481
達內程序員培訓西安 瀏覽:505
人保送車主惠app上怎麼年檢 瀏覽:604
android手機開機密碼 瀏覽:480
linux查看某個進程命令 瀏覽:529
閑置的騰訊雲伺服器 瀏覽:438
rar壓縮包mac 瀏覽:628
php混淆加密工具 瀏覽:582
java把數字拆分 瀏覽:466