Linux的同步機制從2.0到2.6以來不斷發(fā)展完善。從最初的原子操作,到后來的信號量,從大內(nèi)核鎖到今天的自旋鎖。這些同步機制的發(fā)展伴隨Linux從單處理器到對稱多處理器的過渡。
伴隨著從非搶占內(nèi)核到搶占內(nèi)核的過度。Linux的鎖機制越來越有效,也越來越復(fù)雜。
1)Linux的內(nèi)核鎖主要是自旋鎖和信號量。
自旋鎖最多只能被一個可執(zhí)行線程持有,如果一個執(zhí)行線程試圖請求一個已被爭用(已經(jīng)被持有)的自旋鎖,那么這個線程就會一直進行忙循環(huán)——旋轉(zhuǎn)——等待鎖重新可用。要是鎖未被爭用,請求它的執(zhí)行線程便能立刻得到它并且繼續(xù)進行。自旋鎖可以在任何時刻防止多于一個的執(zhí)行線程同時進入臨界區(qū)。
Linux中的信號量是一種睡眠鎖。如果有一個任務(wù)試圖獲得一個已被持有的信號量時,信號量會將其推入等待隊列,然后讓其睡眠。這時處理器獲得自由去執(zhí)行其它代碼。當持有信號量的進程將信號量釋放后,在等待隊列中的一個任務(wù)將被喚醒,從而便可以獲得這個信號量。
信號量的睡眠特性,使得信號量適用于鎖會被長時間持有的情況;只能在進程上下文中使用,因為中斷上下文中是不能被調(diào)度的;另外當代碼持有信號量時,不可以再持有自旋鎖。
Linux 內(nèi)核中的同步機制:原子操作、信號量、讀寫信號量和自旋鎖的API,另外一些同步機制,包括大內(nèi)核鎖、讀寫鎖、大讀者鎖、RCU (Read-Copy Update,顧名思義就是讀-拷貝修改),和順序鎖。
2) Linux中的用戶模式和內(nèi)核模式是什么含意?
MS-DOS等操作系統(tǒng)在單一的CPU模式下運行,但是一些類Unix的操作系統(tǒng)則使用了雙模式,可以有效地實現(xiàn)時間共享。在Linux機器上,CPU要么處于受信任的內(nèi)核模式,要么處于受限制的用戶模式。除了內(nèi)核本身處于內(nèi)核模式以外,所有的用戶進程都運行在用戶模式之中。
內(nèi)核模式的代碼可以無限制地訪問所有處理器指令集以及全部內(nèi)存和I/O空間。如果用戶模式的進程要享有此特權(quán),它必須通過系統(tǒng)調(diào)用向設(shè)備驅(qū)動程序或其他內(nèi)核模式的代碼發(fā)出請求。另外,用戶模式的代碼允許發(fā)生缺頁,而內(nèi)核模式的代碼則不允許。
在2.4和更早的內(nèi)核中,僅僅用戶模式的進程可以被上下文切換出局,由其他進程搶占。除非發(fā)生以下兩種情況,否則內(nèi)核模式代碼可以一直獨占CPU:
(1) 它自愿放棄CPU;
(2) 發(fā)生中斷或異常。
2.6內(nèi)核引入了內(nèi)核搶占,大多數(shù)內(nèi)核模式的代碼也可以被搶占。
3) 怎樣申請大塊內(nèi)核內(nèi)存?
在Linux內(nèi)核環(huán)境下,申請大塊內(nèi)存的成功率隨著系統(tǒng)運行時間的增加而減少,雖然可以通過vmalloc系列調(diào)用申請物理不連續(xù)但虛擬地址連續(xù)的內(nèi)存,但畢竟其使用效率不高且在32位系統(tǒng)上vmalloc的內(nèi)存地址空間有限。所以,一般的建議是在系統(tǒng)啟動階段申請大塊內(nèi)存,但是其成功的概率也只是比較高而已,而不是100%。如果程序真的比較在意這個申請的成功與否,只能退用“啟動內(nèi)存”(Boot Memory)。下面就是申請并導(dǎo)出啟動內(nèi)存的一段示例代碼:
void* x_bootmem = NULL;
EXPORT_SYMBOL(x_bootmem);
unsigned long x_bootmem_size = 0;
EXPORT_SYMBOL(x_bootmem_size);
static int __init x_bootmem_setup(char *str)
{
x_bootmem_size = memparse(str, &str);
x_bootmem = alloc_bootmem(x_bootmem_size);
printk(“Reserved %lu bytes from %p for x\n”, x_bootmem_size, x_bootmem);
return 1;
}
__setup(“x-bootmem=”, x_bootmem_setup);
可見其應(yīng)用還是比較簡單的,不過利弊總是共生的,它不可避免也有其自身的限制:
內(nèi)存申請代碼只能連接進內(nèi)核,不能在模塊中使用。
被申請的內(nèi)存不會被頁分配器和slab分配器所使用和統(tǒng)計,也就是說它處于系統(tǒng)的可見內(nèi)存之外,即使在將來的某個地方你釋放了它。
一般用戶只會申請一大塊內(nèi)存,如果需要在其上實現(xiàn)復(fù)雜的內(nèi)存管理則需要自己實現(xiàn)。
在不允許內(nèi)存分配失敗的場合,通過啟動內(nèi)存預(yù)留內(nèi)存空間將是我們唯一的選擇。
4) 用戶進程間通信主要哪幾種方式?
(1)管道(Pipe):管道可用于具有親緣關(guān)系進程間的通信,允許一個進程和另一個與它有共同祖先的進程之間進行通信。
(2)命名管道(named pipe):命名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關(guān)系進程間的通信。命名管道在文件系統(tǒng)中有對應(yīng)的文件名。命名管道通過命令mkfifo或系統(tǒng)調(diào)用mkfifo來創(chuàng)建。
(3)信號(Signal):信號是比較復(fù)雜的通信方式,用于通知接受進程有某種事件發(fā)生,除了用于進程間通信外,進程還可以發(fā)送信號給進程本身;linux除了支持Unix早期信號語義函數(shù)sigal外,還支持語義符合Posix.1標準的信號函數(shù)sigaction(實際上,該函數(shù)是基于BSD的,BSD為了實現(xiàn)可靠信號機制,又能夠統(tǒng)一對外接口,用sigaction函數(shù)重新實現(xiàn)了signal函數(shù))。
(4)消息(Message)隊列:消息隊列是消息的鏈接表,包括Posix消息隊列system V消息隊列。有足夠權(quán)限的進程可以向隊列中添加消息,被賦予讀權(quán)限的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺
(5)共享內(nèi)存:使得多個進程可以訪問同一塊內(nèi)存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設(shè)計的。往往與其它通信機制,如信號量結(jié)合使用,來達到進程間的同步及互斥。
(6)信號量(semaphore):主要作為進程間以及同一進程不同線程之間的同步手段。
(7)套接字(Socket):更為一般的進程間通信機制,可用于不同機器之間的進程間通信。起初是由Unix系統(tǒng)的BSD分支開發(fā)出來的,但現(xiàn)在一般可以移植到其它類Unix系統(tǒng)上:Linux和System V的變種都支持套接字。
5) 通過伙伴系統(tǒng)申請內(nèi)核內(nèi)存的函數(shù)有哪些?
在物理頁面管理上實現(xiàn)了基于區(qū)的伙伴系統(tǒng)(zone based buddy system)。對不同區(qū)的內(nèi)存使用單獨的伙伴系統(tǒng)(buddy system)管理,而且獨立地監(jiān)控空閑頁。相應(yīng)接口alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。
6) 通過slab分配器申請內(nèi)核內(nèi)存的函數(shù)有?
7) Linux的內(nèi)核空間和用戶空間是如何劃分的(以32位系統(tǒng)為例)?
8) vmalloc()申請的內(nèi)存有什么特點?
9) 用戶程序使用malloc()申請到的內(nèi)存空間在什么范圍?
10) 在支持并使能MMU的系統(tǒng)中,Linux內(nèi)核和用戶程序分別運行在物理地址模式還是虛擬地址模式?
11) ARM處理器是通過幾級也表進行存儲空間映射的?
12) Linux是通過什么組件來實現(xiàn)支持多種文件系通的?
13) Linux虛擬文件系統(tǒng)的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)有哪些?(至少寫出四個)
14) 對文件或設(shè)備的操作函數(shù)保存在那個數(shù)據(jù)結(jié)構(gòu)中?
15) Linux中的文件包括哪些?
16) 創(chuàng)建進程的系統(tǒng)調(diào)用有那些?
17) 調(diào)用schedule()進行進程切換的方式有幾種?
18) Linux調(diào)度程序是根據(jù)進程的動態(tài)優(yōu)先級還是靜態(tài)優(yōu)先級來調(diào)度進程的?
19) 進程調(diào)度的核心數(shù)據(jù)結(jié)構(gòu)是哪個?
20) 如何加載、卸載一個模塊?
21) 模塊和應(yīng)用程序分別運行在什么空間?
22) Linux中的浮點運算由應(yīng)用程序?qū)崿F(xiàn)還是內(nèi)核實現(xiàn)?
23) 模塊程序能否使用可鏈接的庫函數(shù)?
24) TLB中緩存的是什么內(nèi)容?
25) Linux中有哪幾種設(shè)備?
26) 字符設(shè)備驅(qū)動程序的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)是哪個?
27) 設(shè)備驅(qū)動程序包括哪些功能函數(shù)?
28) 如何唯一標識一個設(shè)備?
29) Linux通過什么方式實現(xiàn)系統(tǒng)調(diào)用?
30) Linux軟中斷和工作隊列的作用是什么?
評論