1. 程式人生 > >網上流傳的Linux核心開發面試題整理

網上流傳的Linux核心開發面試題整理

1)      Linux中主要有哪幾種核心鎖?
Linux的核心鎖主要是自旋鎖和訊號量。自旋鎖最多隻能被一個可執行執行緒持有,如果一個執行執行緒試圖請求一個已被爭用(已經被持有)的自旋鎖,那麼這個執行緒就會一直進行忙迴圈——旋轉——等待鎖重新可用。要是鎖未被爭用,請求它的執行執行緒便能立刻得到它並且繼續進行。自旋鎖可以在任何時刻防止多於一個的執行執行緒同時進入臨界區。
Linux
中的訊號量是一種睡眠鎖。如果有一個任務試圖獲得一個已被持有的訊號量時,訊號量會將其推入等待佇列,然後讓其睡眠。這時處理器獲得自由去執行其它程式碼。當持有訊號量的程序將訊號量釋放後,在等待佇列中的一個任務將被喚醒,從而便可以獲得這個訊號量。
訊號量的睡眠特性,使得訊號量適用於鎖會被長時間持有的情況;只能在程序上下文中使用,因為中斷上下文中是不能被排程的;另外當代碼持有訊號量時,不可以再持有自旋鎖。

2)      Linux中的使用者模式和核心模式是什麼含意?
    MS-DOS等作業系統在單一的CPU模式下執行,但是一些類Unix的作業系統則使用了雙模式,可以有效地實現時間共享。在Linux機器上,CPU要麼處於受信任的核心模式,要麼處於受限制的使用者模式。除了核心本身處於核心模式以外,所有的使用者程序都執行在使用者模式之中。
核心模式的程式碼可以無限制地訪問所有處理器指令集以及全部記憶體和I/O空間。如果使用者模式的程序要享有此特權,它必須通過系統呼叫向裝置驅動程式或其他核心模

式的程式碼發出請求。另外,使用者模式的程式碼允許發生缺頁,而核心模式的程式碼則不允許。
 在2.4和更早的核心中,僅僅使用者模式的程序可以被上下文切換出局,由其他程序搶佔。除非發生以下兩種情況,否則核心模式程式碼可以一直獨佔CPU:
(1) 它自願放棄CPU;

(2) 發生中斷或異常。

2.6核心引入了核心搶佔,大多數核心模式的程式碼也可以被搶佔。

3)      怎樣申請大塊核心記憶體?

    在Linux核心環境下,申請大塊記憶體的成功率隨著系統執行時間的增加而減少,雖然可以通過vmalloc系列呼叫申請物理不連續但虛擬地址連續的記憶體,但畢竟其使用效率不高且在32位系統上vmalloc的記憶體地址空間有限。所以,一般的建議是在系統啟動階段申請大塊記憶體,但是其成功的概率也只是比較高而已,而不是100%。如果程式真的

比較在意這個申請的成功與否,只能退用“啟動記憶體”(Boot Memory)

4)      使用者程序間通訊主要哪幾種方式?
    (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的變種都支援套接字。

5)      通過夥伴系統申請核心記憶體的函式有哪些?

    在物理頁面管理上實現了基於區的夥伴系統(zone based buddy system)。對不同區的記憶體使用單獨的夥伴系統(buddy system)管理,而且獨立地監控空閒頁。相應介面alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。

    補充知識:

1.原理說明

Linux核心中採用了一種同時適用於32位和64位系統的內存分頁模型,對於32位系統來說,兩級頁表足夠用了,而在x86_64統中,用到了四級頁表。

頁全域性目錄(Page Global Directory)

頁上級目錄(Page Upper Directory)

頁中間目錄(Page Middle Directory)

頁表(Page Table)

  頁全域性目錄包含若干頁上級目錄的地址,頁上級目錄又依次包含若干頁中間目錄的地址,而頁中間目錄又包含若干頁表的地址,每一個頁表項指向一個頁框。Linux中採用4KB大小的頁框作為標準的記憶體分配單元。

  多級分頁目錄結構

1.1.夥伴系統演算法

  在實際應用中,經常需要分配一組連續的頁框,而頻繁地申請和釋放不同大小的連續頁框,必然導致在已分配頁框的記憶體塊中分散了許多小塊的空閒頁框。這樣,即使這些頁框是空閒的,其他需要分配連續頁框的應用也很難得到滿足。

  為了避免出現這種情況,Linux核心中引入了夥伴系統演算法(buddy system)。把所有的空閒頁框分組為11塊連結串列,每個塊連結串列分別包含大小為12481632641282565121024個連續頁框的頁框塊。最大可以申請1024個連續頁框,對應4MB大小的連續記憶體。每個頁框塊的第一個頁框的實體地址是該塊大小的整數倍。

  假設要申請一個256個頁框的塊,先從256個頁框的連結串列中查詢空閒塊,如果沒有,就去512頁框的連結串列中找,找到了則將頁框塊分為2256頁框的塊,一個分配給應用,另外一個移到256個頁框的連結串列中。如果512個頁框的連結串列中仍沒有空閒塊,繼續向1024個頁框的連結串列查詢,如果仍然沒有,則返回錯誤。

  頁框塊在釋放時,會主動將兩個連續的頁框塊合併為一個較大的頁框塊。

1.2.slab分配器

slab分配器源於 Solaris 2.4 分配演算法,工作於物理記憶體頁框分配器之上,管理特定大小物件的快取,進行快速而高效的記憶體分配。

slab分配器為每種使用的核心物件建立單獨的緩衝區。Linux 核心已經採用了夥伴系統管理實體記憶體頁框,因此 slab分配器直接工作於夥伴系統之上。每種緩衝區由多個 slab 組成,每個 slab就是一組連續的實體記憶體頁框,被劃分成了固定數目的物件。根據物件大小的不同,預設情況下一個 slab 最多可以由 1024個頁框構成。出於對齊等其它方面的要求,slab 中分配給物件的記憶體可能大於使用者要求的物件實際大小,這會造成一定的記憶體浪費。

2.常用記憶體分配函式

2.1.__get_free_pages

unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)

__get_free_pages函式是最原始的記憶體分配方式,直接從夥伴系統中獲取原始頁框,返回值為第一個頁框的起始地址。__get_free_pages在實現上只是封裝了alloc_pages數,從程式碼分析,alloc_pages函式會分配長度為1<

2.2.kmem_cache_alloc

struct kmem_cache *kmem_cache_create(const char *name, size_t size,

size_t align, unsigned long flags,

void (*ctor)(void*, struct kmem_cache *, unsigned long),

void (*dtor)(void*, struct kmem_cache *, unsigned long))

void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags)

kmem_cache_create/ kmem_cache_alloc是基於slab分配器的一種記憶體分配方式,適用於反覆分配釋放同一大小記憶體塊的場合。首先用kmem_cache_create建立一個快取記憶體區域,然後用kmem_cache_alloc該快取記憶體區域中獲取新的記憶體塊。kmem_cache_alloc一次能分配的最大記憶體由mm/slab.c檔案中的MAX_OBJ_ORDER巨集定義,在預設的2.6.18核心版本中,該巨集定義為5於是一次最多能申請1<<5 * 4KB也就是128KB連續實體記憶體。分析核心原始碼發現,kmem_cache_create函式的size引數大於128KB時會呼叫BUG()。測試結果驗證了分析結果,用kmem_cache_create配超過128KB的記憶體時使核心崩潰。

2.3.kmalloc

void *kmalloc(size_t size, gfp_t flags)

kmalloc是核心中最常用的一種記憶體分配方式,它通過呼叫kmem_cache_alloc數來實現。kmalloc一次最多能申請的記憶體大小由include/linux/Kmalloc_size.h內容來決定,在預設的2.6.18核心版本中,kmalloc次最多能申請大小為131702B也就是128KB節的連續實體記憶體。測試結果表明,如果試圖用kmalloc函式分配大於128KB的記憶體,編譯不能通過。

2.4.vmalloc

void *vmalloc(unsigned long size)

  前面幾種記憶體分配方式都是物理連續的,能保證較低的平均訪問時間。但是在某些場合中,對記憶體區的請求不是很頻繁,較高的記憶體訪問時間也可以接受,這是就可以分配一段線性連續,物理不連續的地址,帶來的好處是一次可以分配較大塊的記憶體。3-1示的是vmalloc分配的記憶體使用的地址範圍。vmalloc一次能分配的記憶體大小沒有明確限制。出於效能考慮,應謹慎使用vmalloc函式。在測試過程中,最大能一次分配1GB的空間。

Linux核心部分記憶體分佈

2.5.dma_alloc_coherent

void *dma_alloc_coherent(struct device *dev, size_t size,

ma_addr_t *dma_handle, gfp_t gfp)

DMA是一種硬體機制,允許外圍裝置和主存之間直接傳輸IO資料,而不需要CPU的參與,使用DMA機制能大幅提高與裝置通訊的吞吐量。DMA操作中,涉及到CPU高速緩存和對應的記憶體資料一致性的問題,必須保證兩者的資料一致,在x86_64體系結構中,硬體已經很好的解決了這個問題,dma_alloc_coherent__get_free_pages函式實現差別不大,前者實際是呼叫__alloc_pages數來分配記憶體,因此一次分配記憶體的大小限制和後者一樣。__get_free_pages分配的內存同樣可以用於DMA操作。測試結果證明,dma_alloc_coherent數一次能分配的最大記憶體也為4M

2.6.ioremap

void * ioremap (unsigned long offset, unsigned long size)

ioremap是一種更直接的記憶體“分配”方式,使用時直接指定物理起始地址和需要分配記憶體的大小,然後將該段實體地址對映到核心地址空間。ioremap用到的實體地址空間都是事先確定的,和上面的幾種記憶體分配方式並不太一樣,並不是分配一段新的實體記憶體。ioremap多用於裝置驅動,可以讓CPU直接訪問外部裝置的IO空間ioremap能對映的記憶體由原有的實體記憶體空間決定,所以沒有進行測試。

2.7.Boot Memory

  如果要分配大量的連續實體記憶體,上述的分配函式都不能滿足,就只能用比較特殊的方式,在Linux核引導階段來預留部分記憶體。

2.7.1.在核心引導時分配記憶體

void* alloc_bootmem(unsigned long size)

  可以在Linux核心引導過程中繞過夥伴系統來分配大塊記憶體。使用方法是在Linux核心引導時,呼叫mem_init函式之前alloc_bootmem函式申請指定大小的記憶體。如果需要在其他地方呼叫這塊記憶體,可以將alloc_bootmem返回的記憶體首地址通過EXPORT_SYMBOL出,然後就可以使用這塊記憶體了。這種記憶體分配方式的缺點是,申請記憶體的程式碼必須在連結到核心中的程式碼裡才能使用,因此必須重新編譯核心,而且記憶體管理系統看不到這部分記憶體,需要使用者自行管理。測試結果表明,重新編譯核心後重啟,能夠訪問引導時分配的記憶體塊。

2.7.2.通過核心引導引數預留頂部記憶體

  在Linux核心引導時,傳入引數“mem=size”保留頂部的記憶體區間。比如系統有256MB存,引數“mem=248M”會預留頂部的8MB記憶體,進入系統後可以呼叫ioremap(0xF8000000x800000)來申請這段記憶體。

3.幾種分配函式的比較

  分配原理最大記憶體其他

__get_free_pages直接對頁框進行操作4MB適用於分配較大量的連續實體記憶體

kmem_cache_alloc基於slab機制實現128KB適合需要頻繁申請釋放相同大小記憶體塊時使用

kmalloc

相關推薦

網上流傳Linux核心開發試題整理

1)      Linux中主要有哪幾種核心鎖?Linux的核心鎖主要是自旋鎖和訊號量。自旋鎖最多隻能被一個可執行執行緒持有,如果一個執行執行緒試圖請求一個已被爭用(已經被持有)的自旋鎖,那麼這個執行緒就會一直進行忙迴圈——旋轉——等待鎖重新可用。要是鎖未被爭用,請求它的執

深信服 linux軟體開發試題整理

1、結構體可以進行比較 int memcmp ( const void * ptr1, const void * ptr2, size_t num ); Compare two blocks of memory Compares the first num bytes of

前端開發--試題整理(JS篇)

狀態 state oda 通過 cli 命名空間 script push arguments 1.截取字符串abcdace的acealert(‘abcdace‘.substring(4)); 2.規避javascript多人開發函數重名問題命名空間封閉空間js模塊化mvc(

linux核心經典試題

                                         LINU

Java開發崗位試題整理

線程數 本地 簡單 線程間通信 syn 低耦合 刪除 不同方法 ola 一、Java基礎 String類為什麽是final的 HashMap的源碼,實現原理,底層結構。 說說你知道的幾個Java集合類:list、set、queue、map實現類。 描述一下A

Linux運維工程師:30道試題整理

11.Linux 系統的開機啟動順序 載入 BIOS–>讀取 MBR–>Boot Loader–>載入核心–>使用者層 init 一句 inittab 檔案來設定系統執行的等級(一般 3 或者 5,3 是多使用者命令列,5 是介面)–>init 程序執行 rc.syninit

2016年終前端HTML5開發試題彙總整理

2016年終前端HTML5開發面試題彙總整理,僅部分問題有答案,其他請自行解決處理。 一、HTML常見題目 01、Doctype作用?嚴格模式與混雜模式如何區分?它們有何意義? 02、HTML5 為什麼只需要寫 <!DOCTYPE HTML>? 答:

linux C/C++伺服器後臺開發試題總結

一、程式語言 1.根據熟悉的語言,談談兩種語言的區別? 主要淺談下C/C++和PHP語言的區別: 1)PHP弱型別語言,一種指令碼語言,對資料的型別不要求過多,較多的應用於Web應用開發,現在好多網際網路開發公司的主流web後臺開發語言,主要框架為mvc模型,如smarty,yaf,升級的PHP7速度較快,

Linux運維工程師:試題整理

11.Linux系統的開機啟動順序 載入BIOS–>讀取MBR–>Boot Loader–>載入核心–>使用者層init一句inittab檔案來設定系統執行的等級(一般3或者5,3是多使用者命令列,5是介面)–>init程序執行rc.syninit–>啟動核心模組

試題整理--開發中實現spring的事務有5種方式

Spring+Hibernate的實質: 就是把Hibernate用到的資料來源Datasource,Hibernate的SessionFactory例項,事務管理器HibernateTransactionManager,都交給Spring管理。 那麼再沒整合之前Hiber

Android開發工程師試題整理(百度)

偏簡單部分: 1. Android dvm(Dalvik VM)的程序和Linux的程序,應用程式的程序是否為同一個概念? DVM是Dalvik虛擬機器。每一個Android應用程式都在自己的程序中執行,都擁有一個獨立的Dalvik虛擬機器例項。而每一個Dalvik虛擬機器

嵌入式linux開發試題解析——C語言部分

 1、編寫統計一個數二進位制表示中有多少個1的函式         int count_bit1(int m)         {      int count = 0;      while(m)      {      m = m & (m-

Android開發試題收集整理

AIDL (Android Interface Definition Language) 是一種IDL 語言,用於生成可以在Android裝置上兩個程序之間進行程序間通訊(interprocess communication, IPC)的程式碼。如果在一個程序中(例如Activity)要呼叫另一個程序中(例如

Linux運維試題

linux運維 面試題總結一下遇到的面試題: 如有錯誤,請讀者指出,感謝!1、使用iptbales如何將本地80端口的請求轉發到8080端口,當前主機ip為192.168.2.1 1)、DNAT實現: iptables -t nat -A PREROUTING -d 192.168.2

oracle 數據庫開發試題

target nco nvl -a font tails 當我 employ index 近期參加了數場面試。總結一下競聘oracle 開發崗位最常問到哪些問題: 1、delete 與 truncate 差別? 1)truncate 是DDL語句,del

【面試】iOS 開發試題(一)

readonly ava obj jce easy 主動 每一個 我不 com   1. #import 跟#include 又什麽差別,@class呢, #import<> 跟 #import””又什麽差別?   答:#import是Obje

web前端開發試題(未完待續)

tex ora 相對 設置 erl 思路 實現 多列 寬度 一、HTML與XHTML的不同:1)XHTML元素必須被正確地嵌套 2)元素必須被關閉 如:<h1>……&l

Python 試題整理1

歸並 遞歸函數 color 算術 div microsoft 變量 ldp 路徑 參考網頁:15 Essential Python Interview Questions 1. 什麽是Python?   可以在回答中與其他技術作對比(鼓勵這麽做);如果應聘的是一個Pytho

java試題整理(1)

pmap 復制 java對象 試題 取出 樹形 年輕代和老年代 com 足夠 1、Equals與==的區別?   ==是判斷兩個變量或者實例是不是指向同一個內存地址   equals是判斷兩個變量或者實例所指向的內存地址中的值是不是相同 2、Object有哪些公用方法?  

10個Linux腳本試題,看看你能答出幾個?

linux 入門 shell 1、寫一個腳本,判斷當前系統上所有用戶的shell是否為可登錄shell(即用戶的shell不是/sbin/nologin);分別這兩類用戶的個數;通過字符串比較來實現; declare -a shell declare sum_login=0