Linux 內核的操作系統是不是得一直運行著?

linux 內核開機後是不是得一直運行著,不然怎麼調度別人?假設只有一個cpu核的話,內核一直在運行,用戶進程怎麼運行?


當年上我老闆的OS課,老闆上來就告訴我們,OS不是運行著的代碼,而是一堆躺在內存里等著被調用的代碼。

內核就是一個由interrupt驅動的程序。這個interrupt可以是一個系統調用(x86下,很多OS的系統調用是靠software interrupt實現的),可以是一個用戶程序產生的異常,也可以是一個硬體產生的事件中斷。

於是你的問題解決了:一個用戶程序運行的時候,Linux就在內存里呆著,等著一個中斷的到來。在這個中斷的處理過程中,來做「調度」。而一般的時分系統里,都會有個timer interrupt每隔一段時間到來,也就是樓上說的「時間片」。

PS:很多人在認識OS的過程中被大量的artificial concept給困惑了。比如神馬進程,線程,調度,micro kernel,monolithic kernel的。從x86架構上來理解OS才是王道。

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

PS of PS: 把評論粘上來,補充上面的PS,謝 @許越提醒:

因為很多教材在講os的時候,更喜歡從app的角度來看待os,於是很多時候被各種概念綁架。因為很多例如進城,線程,系統調用這樣的東西都是由os在硬體上抽象出來的。站在這些概念上看os,就有點「不識廬山真面目」的感覺。所以我的意思是從硬體的角度看os,反過來理解為何os要抽象出這些概念。站在cpu的角度,理解指令是怎麼在cpu上一條一條的運行的。


在linux0.11中是,有個ID號為0的進程,循環調用puase()函數,而puase()又會調用schedule()函數,schedule()函數會檢查有沒有可調度的進程,有就調度,沒有就又返回,然後再puase()。

當你要運行一個程序時,比如你用鍵盤輸入一個程序名來運行時,就產生鍵盤中斷,系統的shell程序將喚醒執行,並解釋你輸入的命令,並運行你輸入的程序。


答案是,Yes。

但是這個「一直運行」並不是調度的基礎。

Linux kernel 的 0 號線程(每個 CPU 一個)里有一個循環,但不是空循環,而是調用電源管理,給 CPU降頻。

把這個循環改成空循環之後,系統完全正常,但是 CPU 的發熱會一直保持在 100% 的狀態。這就是早期沒有電源管理的 386/486 的工作狀態。對於沒有電源管理的 CPU,這部分代碼是被條件編譯忽略的。基本等同於空循環。

0 號進程並不負責調度其它進程。它也會調用 scheduler,但是這個調用和其它進程通過 system call 讓出 CPU 是等同的,並非它獨有。而且 scheduler 還可以被時鐘中斷調起的。

0 號進程的優先順序最低(低到連 scheduler 的 starving-prevention 策略也不會考慮它)。所以每次 scheduler 被時鐘中斷,或者 system call 喚起的時候,只要有其它用戶進程需要運行,就不會輪到它。但是現代系統里 99% 的時間還是 0 號進程在運行,這就是系統的 IDLE 時間。

最高票 @高鵬 的答案並不正確。OS kernel 的大部分代碼確實是「躺著」這是從 kernel 代碼的靜態覆蓋來說。但是 CPU 不會處於一個僵死的狀態。CPU 是永遠處於運行代碼的狀態的,從這個方面來說,CPU 99% 的時間都在運行同樣的幾十行 kernel 代碼。


不是一直運行,一般來說大部分時間運行的是用戶代碼。至於如何調度,利用中斷,陷入門等實現。


內核代碼是一堆被硬體中斷(跳線,時鐘,異常)和軟體中斷(系統調用)逼著運行的代碼。。

正常的內核操作系統代碼(不包括內核態驅動)裡頭不會有無限死循環這種貨(驅動我管不著哈,粗製濫造的移植驅動有不返回的函數並不奇怪)。


內核:來你優先順序高你運行幾毫秒。我先去躺著。

藍後程序A就去處理器上run了

程序A:我運行完了。叫內核起來,他安排下一位。

內核又叫程序B上了,但是B很不自覺,一直占著處理器。於是內核越來越不滿它(每隔一點時間調低他的優先順序)。

終於內核忍不住了:你給我下來!

然後內核又從進程隊列找優先順序最高的運行,然後又去躺一會。

哎瑪有優先順序比你高的來了,你運行到哪了我給你記著。(中斷,中斷是由相關硬體執行的,到了中斷時CPU會切換到高優先順序代碼段)

內核運行的時候:好多人啊我先算算讓誰先(內核進程調度)


最基礎的調度是用時鐘中斷搞的,每隔若干時間,外面的晶元就會給 cpu 發個時鐘中斷 int 20h,此時操作系統(更具體而言是一個中斷處理程序)攔截這個中斷,保存當前 cpu 狀態(寄存器、頁表,等等),把另一個進程保存的狀態恢復進去,然後結束中斷,切換進程。

軟體調用操作系統的功能也是用中斷(軟中斷),linux 底下(曾經)是 int 80h,現在用 sysenter。


如果題主對這些具體的知識非常感興趣的話,可以去看intel編程手冊,它裡面有一本教你用x86寫操作系統。這跟《操作系統》互為補充,一本理論,一本實現。


本質:

  1. 內核的1個任務是管理好硬體,服務好硬體。

  2. 內核的2個任務是管理好應用,服務好應用。

在以上兩個任務中,最最重要的任務是管理好內存。

因為大家都在內存里排隊等著用cpu。所以kernel得制定規則維護秩序。

許可權:

kernel在制定規則的時候受我大天朝戶口制度的啟發,規定:

  1. kernel屬於城市戶口享有特權;

  2. app 屬於農村戶口,某些事情需要進城(交給kernel陷入內核),kernel像官老爺一樣來給你來處理,比如某些對設備的具體操控,處理完了把數據結果告訴你;如果你要計算1+1=2那到不用進城。

中斷:

  1. 官老爺還養了一條狗,這條狗定時會叫(硬中斷),官老爺用它來計時,以此分配每個app的用時。當然還有其他硬中斷,這些會直接通過電路的某個管腳直接反饋上去。

  2. 當app在幹活的時候,kernel也隨時standby,除了上面說的想做超過自己許可權的事情得打報告等結果。同時kernel還監控app的運行,哪裡出現個除零操作啊非法地址操作段錯誤啊等等也會被kernel獲知(軟中斷),kernel就在此接管給你個coredump。

概念:

  1. 躺在硬碟里的叫程序。

  2. 從硬碟里跑到內存可以隨時執行的叫進程。

  3. 在進程這個主幹上又可以分多條控制流,比如一個活得分身兩人才行:一個望風,一個幹活,望風的有情況隨時通知幹活,所以他們之間得通信,黑話叫同步。

  4. 調度很好理解但工作不好做,因為總得照顧好VIP和屌絲之間平衡。

  5. 微內核就是非常懶得一種內核,懶到他只負責各大模塊的通信,其他一概不管。

  6. 宏內核就是恰恰相反的一種,什麼調度驅動文件系統通信他都管。

書:

  • 對於書的話,你要是能把那些intel的大部頭英文手冊看進去那真是NB。

  • 要是不行的話就從簡單的開始吧,陳莉君有本很薄的書可以從它開始。

  • 光看書還是沒用的還得看kernel源碼,看的時候時刻提醒自己,kernel與其他app不同的地方是,kernel處理的數據是內存!你會看到一堆堆的地址處理。

最後,Nachos是赫赫有名的教學用OS。萬分推薦。

The End


最近在研究深入理解linux內核,雖然這本書不知是寫的原因還是翻譯的太差,總給人一種邏輯不到位,前言不搭後語的感覺。但是,關於內核是啥,有個很形象的說法:內核就相當於CS體系中的伺服器,為其他進程提供服務!


試圖寫一個簡單易懂的答案

內核機制簡單了說…和課程表一樣的概念。

一個學期,你需要上好幾門課。然後你肯定不會一次性,一課上一節,一節上滿整個課程內容。那麼就得每周分開上幾節課,每節40分鐘這樣的,這樣一個學期下來,你很多門課總共上夠了學時,就上完了。

就這麼個原理。

沒課的時候,你做你的事情,睡覺打遊戲。

沒事的時候操作系統執行自己的代碼,比如維護這個那個。

有要學習的內容的時候,你就每周上幾節課。一節上夠45分鐘就下課。

有任務程序的時候,系統會跳轉讓用戶程序執行,一定時間後就跳轉回系統。

上下一節課

調用(跳轉運行到)下一個正在進行的用戶程序

一個學期以後,你的幾個科目都上夠學時了。

一段時間後,用戶程序就執行完畢了。

而每周就是你上課安排課程表的單位。

每次循環這樣一個個執行所有任務。

最終把這個過程一直加快到很快很快的速度。

你就覺得是調用了程序了。而且你會覺得很多程序同時在運行。

現在的操作系統,在內部有多層抽象把這些東西一層一層分開,你就更難體會到這個東西了。


高票答案裡面,高鵬的答案是對的。馮東的反對是強行反對。內核肯定不是一直運行啊。內核的作用就是提供調度和特權資源訪問(內存,外設IO埠等等)啊,如果用戶態的應用程序不需要的話,內核還運行,那不是在搗亂嗎?特別是用戶態運行高計算負載程序時,還要特別的避免內核時鐘中斷帶來的計算性能抖動。並且多核CPU其中的核是可以熱插拔的,可以下線的,並不是每個核得一直運行的。


不是。

一個cpu的話,如果時間片夠小的話,一個時間片內就只有一個程序在執行。

其他程序怎麼執行?

內核服務停了,讓他們執行就執行了。

搶佔式的操作系統允許程序沒執行完,cpu控制權就移交給別的程序,比如內核,然後內核又可以執行了。

建議去看看進程調度相關資料,以及一些調度演算法,操作系統的設計是很有意思的事情,因為它和現實中的其他系統一樣,面臨著資源分配的問題,所以你可以看到像銀行儲備金這樣的虛擬內存機制。


所有程序都是在cpu上執行的,當你自己的程序在執行的時候,其實系統是不執行的,要從單位cpu指令的view去看系統與程序的執行。如果cpu上只有一個程序,那根本就不需要操作系統,比如很多微控制器根本就不用系統,一個loop就搞定了所有的工作。程序多了,但cpu只有一個,那麼就需要安排一下在某段時間誰在cpu上運行,那麼就產生了操作系統,它就是調度程序用的。於是仍然可以把他理解成一個loop,循環檢查看有沒有程序要使用cpu,如果有就吧cpu交給這個程序,但是為了防止這個程序佔用時間太長而耽誤其他程序的工作,那麼就在這個程序執行一會兒之後將cpu的使用權切換給另一個程序,於是從宏觀上看大家都在運行。


最近在看 (操作系統:精髓與設計原理)。

這本書應該能解決你的疑惑。


調度的信號是硬體中斷和軟中斷髮出。內核程序會很nice地讓用戶程序運行。因為中斷要陷入內核,用戶程序身不由己。


分頁阅读: 1 2