Linux 的同步機制從 2.0 到 2.6 以來不斷髮展完善。從最初的原子操做,到後來的信號量,從 大內核鎖到今天的自旋鎖。這些同步機制的發展伴隨 Linux 從單處理器到對稱多處理器的 過渡;
伴隨着從非搶佔內核到搶佔內核的過分。Linux 的鎖機制愈來愈有效,也愈來愈複雜。 Linux 的內核鎖主要是自旋鎖和信號量。
自旋鎖最多隻能被一個可執行線程持有,若是一個執行線程試圖請求一個已被爭用(已經被 持有)的自旋鎖,那麼這個線程就會一直進行忙循環——旋轉——等待鎖從新可用。要是鎖 未被爭用,請求它的執行線程便能馬上獲得它而且繼續進行。自旋鎖能夠在任什麼時候刻防止多 於一個的執行線程同時進入臨界區。
Linux 中的信號量是一種睡眠鎖。若是有一個任務試圖得到一個已被持有的信號量時,信號 量會將其推入等待隊列,而後讓其睡眠。這時處理器得到自由去執行其它代碼。當持有信號 量的進程將信號量釋放後,在等待隊列中的一個任務將被喚醒,從而即可以得到這個信號量。
信號量的睡眠特性,使得信號量適用於鎖會被長時間持有的狀況;只能在進程上下文中使用, 由於中斷上下文中是不能被調度的;另外當代碼持有信號量時,不能夠再持有自旋鎖。
Linux 內核中的同步機制:原子操做、信號量、讀寫信號量和自旋鎖的 API,另一些同步機 制,包括大內核鎖、讀寫鎖、大讀者鎖、RCU (Read-Copy Update,顧名思義就是讀-拷貝修 改),和順序鎖。node
MS-DOS 等操做系統在單一的 CPU 模式下運行,可是一些類 Unix 的操做系統則使用了雙 模式,能夠有效地實現時間共享。在 Linux 機器上,CPU 要麼處於受信任的內核模式,要麼處 於受限制的用戶模式。除了內核自己處於內核模式之外,全部的用戶進程都運行在用戶模式之中。
內核模式的代碼能夠無限制地訪問全部處理器指令集以及所有內存和 I/O 空間。若是用戶 模式的進程要享有此特權,它必須經過系統調用向設備驅動程序或其餘內核模式的代碼發出請求。另外,用戶模式的代碼容許發生缺頁,而內核模式的代碼則不容許。
在 2.4 和更早的內核中,僅僅用戶模式的進程能夠被上下文切換出局,由其餘進程搶佔。除非 發生如下兩種狀況,不然內核模式代碼能夠一直獨佔 CPU:
(1) 它自願放棄 CPU;
(2) 發生中斷或異常。
2.6 內核引入了內核搶佔,大多數內核模式的代碼也能夠被搶佔。linux
在 Linux 內核環境下,申請大塊內存的成功率隨着系統運行時間的增長而減小,雖然能夠經過 vmalloc 系列調用申請物理不連續但虛擬地址連續的內存,但畢竟其使用效率不高且在 32 位 系統上 vmalloc 的內存地址空間有限。因此,通常的建議是在系統啓動階段申請大塊內存,但 是其成功的機率也只是比較高而已,而不是 100%。若是程序真的比較在乎這個申請的成功 與否,只能退用「啓動內存」(Boot Memory)。下面就是申請並導出啓動內存的一段示例代碼:算法
可見其應用仍是比較簡單的,不過利弊老是共生的,它不可避免也有其自身的限制: 內存申請代碼只能鏈接進內核,不能在模塊中使用。
被申請的內存不會被頁分配器和 slab 分配器所使用和統計,也就是說它處於系統的可見內 存以外,即便在未來的某個地方你釋放了它。
通常用戶只會申請一大塊內存,若是須要在其上實現複雜的內存管理則須要本身實現。 在不容許內存分配失敗的場合,經過啓動內存預留內存空間將是咱們惟一的選擇。緩存
(1)管道(Pipe):管道可用於具備親緣關係進程間的通訊,容許一個進程和另外一個與它有共同祖 先的進程之間進行通訊。
(2)命名管道(named pipe):命名管道克服了管道沒有名字的限制,所以,除具備管道所具備的 功能外,它還容許無親緣關係進程間的通訊。命名管道在文件系統中有對應的文件名。命名 管道經過命令 mkfifo 或系統調用 mkfifo 來建立。
(3)信號(Signal):信號是比較複雜的通訊方式,用於通知接受進程有某種事件發生,除了用於進 程間通訊外,進程還能夠發送信號給進程自己;linux 除了支持 Unix 早期信號語義函數 sigal 外,還支持語義符合 Posix.1 標準的信號函數 sigaction(實際上,該函數是基於 BSD 的,BSD 爲了實現可靠信號機制,又可以統一對外接口,用 sigaction 函數從新實現了 signal 函數)。
(4)消息(Message)隊列:消息隊列是消息的連接表,包括 Posix 消息隊列 system V 消息隊 列。有足夠權限的進程能夠向隊列中添加消息,被賦予讀權限的進程則能夠讀走隊列中的消 息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節流以及緩衝區大小受限等 缺
(5)共享內存:使得多個進程能夠訪問同一塊內存空間,是最快的可用 IPC 形式。是針對其餘 通訊機制運行效率較低而設計的。每每與其它通訊機制,如信號量結合使用,來達到進程間 的同步及互斥。
(6)信號量(semaphore):主要做爲進程間以及同一進程不一樣線程之間的同步手段。
(7)套接字(Socket):更爲通常的進程間通訊機制,可用於不一樣機器之間的進程間通訊。起初是 由 Unix 系統的 BSD 分支開發出來的,但如今通常能夠移植到其它類 Unix 系統上:Linux 和 System V 的變種都支持套接字。markdown
在物理頁面管理上實現了基於區的夥伴系統(zone based buddy system)。對不一樣區的內存 使用單獨的夥伴系統(buddy system)管理,並且獨立地監控空閒頁。相應接口 alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。數據結構
struct super_block,struct inode,struct file,struct dentry;併發
struct file_operations函數
執行文件,普通文件,目錄文件,連接文件和設備文件,管道文件。spa
clone(),fork(),vfork();系統調用服務例程:sys_clone,sys_fork,sys_vfork;操作系統
1.系統調用 do_fork();
2.定時中斷 do_timer();
3.喚醒進程 wake_up_process
4.改變進程的調度策略 setscheduler();
5.系統調用禮讓 sys_sched_yield();
Liunx 調度程序是根據根據進程的動態優先級來調度進程的,可是動態優先級又是根據靜態 優先級根據算法計算出來的,二者是兩個相關聯的值。由於高優先級的進程老是比低優先級
的進程先被調度,爲防止多個高優先級的進程佔用 CPU 資源,致使其餘進程不能佔有 CPU, 因此引用動態優先級概念
struct runqueue
insmod 加載,rmmod 卸載
模塊運行在內核空間,應用程序運行在用戶空間
應用程序實現,Linux 中的浮點運算是利用數學庫函數實現的,庫函數可以被應用程序連接後 調用,不能被內核連接調用。這些運算是在應用程序中運行的,而後再把結果反饋給系統。 Linux 內核若是必定要進行浮點運算,須要在創建內核時選上 math-emu,使用軟件模擬計算 浮點運算,聽說這樣作的代價有兩個:用戶在安裝驅動時須要重建內核,可能會影響到其餘的 應用程序,使得這些應用程序在作浮點運算的時候也使用 math-emu,大大的下降了效率。
模塊程序運行在內核空間,不能連接庫函數。
TLB,頁表緩存,當線性地址被第一次轉換成物理地址的時候,將線性地址和物理地址的對應 放到 TLB 中,用於下次訪問這個線性地址時,加快轉換速度。
字符設備和塊設備。網卡是例外,他不直接與設備文件對應,mknod 系統調用用來建立設備 文件。
字符設備描述符 struct cdev,cdev_alloc()用於動態的分配 cdev 描述符,cdev_add()用於注 冊一個 cdev 描述符,cdev 包含一個 struct kobject 類型的數據結構它是核心的數據結構
open(),read(),write(),llseek(),realse();
Linux 使用一個設備編號來惟一的標示一個設備,設備編號分爲:主設備號和次設備號,通常主 設備號標示設備對應的驅動程序,次設備號對應設備文件指向的設備,在內核中使用 dev_t 來 表示設備編號,通常它是 32 位長度,其中 12 位用於表示主設備號,20 位用於表示次設備號, 利用 MKDEV(int major,int minor);用於生成一個 dev_t 類型的對象。
靠軟件中斷實現的,首先,用戶程序爲系統調用設置參數,其中一個編號是系統調用編號,參數 設置完成後,程序執行系統調用指令,x86 上的軟中斷是有 int 產生的,這個指令會致使一個異 常,產生一個事件,這個事件會致使處理器跳轉到內核態並跳轉到一個新的地址。並開始處 理那裏的異常處理程序,此時的異常處理就是系統調用程序。
Linux 中的軟中斷和工做隊列是中斷處理。
1.軟中斷通常是「可延遲函數」的總稱,它不能睡眠,不能阻塞,它處於中斷上下文,不能進城切 換,軟中斷不能被本身打斷,只能被硬件中斷打斷(上半部),能夠併發的運行在多個 CPU 上。 因此軟中斷必須設計成可重入的函數,所以也須要自旋鎖來保護其數據結構。
2.工做隊列中的函數處在進程上下文中,它能夠睡眠,也能被阻塞,可以在不一樣的進程間切 換。已完成不一樣的工做。 可延遲函數和工做隊列都不能訪問用戶的進程空間,可延時函數在執行時不可能有任何正在 運行的進程,工做隊列的函數有內核進程執行,他不能訪問用戶空間地址
看到這裏的小夥伴,若是你喜歡這篇文章的話,別忘了轉發、收藏、留言互動!
若是對文章有任何問題,歡迎在留言區和我交流~
最近我新整理了一些Java資料,包含面經分享、模擬試題、和視頻乾貨,若是你須要的話,歡迎私信我!