linux 驅動程式一般工作在核心空間,但也可以工作在使用者空間。下面我們將詳細解析,什麼是核心空間,什麼是使用者空間,以及如何判斷他們。
Linux 簡化了分段機制,使得虛擬地址與線性地址總是一致,因此,Linux 的虛擬地址空間也為 0~4G 。 Linux 核心將這 4G 位元組的空間分為兩部分。將最高的 1G 位元組(從虛擬地址 0xC0000000 到 0xFFFFFFFF),供核心使用,稱為 “核心空間” 。而將較低的 3G 位元組(從虛擬地址 0x00000000 到 0xBFFFFFFF),供各個程式使用,稱為 “使用者空間)。因為每個程式可以透過系統呼叫進入核心,因此,Linux 核心由系統內的所有程式共享。於是,從具體程式的角度來看,每個程式可以擁有 4G 位元組的虛擬空間。
Linux 使用兩級保護機制:0 級供核心使用,3 級供使用者程式使用。從圖中可以看出(這裡無法表示圖),每個程式有各自的私有使用者空間(0~3G),這個空間對系統中的其他程式是不可見的。最高的 1GB 位元組虛擬核心空間則為所有程式以及核心所共享。
核心空間中存放的是核心程式碼和資料,而程式的使用者空間中存放的是使用者程式的程式碼和資料。不管是核心空間還是使用者空間,它們都處於虛擬空間中。
雖然核心空間佔據了每個虛擬空間中的最高 1GB 位元組,但對映到實體記憶體卻總是從最低地址(0x00000000)開始。對核心空間來說,其地址對映是很簡單的線性對映,0xC0000000 就是實體地址與線性地址之間的位移量,在 Linux 程式碼中就叫做 PAGE_OFFSET 。
核心空間和使用者空間之間如何進行通訊?
核心空間和使用者空間一般透過系統呼叫進行通訊。
如何判斷一個驅動是使用者模式驅動還是核心模式驅動?  判斷的標準是什麼?
使用者空間模式的驅動一般透過系統呼叫來完成對硬體的訪問,如透過系統呼叫將驅動的 io 空間對映到使用者空間等。因此,主要的判斷依據就是系統呼叫。
核心空間和使用者空間上不同太多了,說不完,比如使用者態的連結串列和核心連結串列不一樣;使用者態用 printf,核心態用 printk;使用者態每個應用程式空間是虛擬的,相對獨立的,核心態中卻不是獨立的,所以程式設計要非常小心。等等。
還有使用者態和核心態程式通訊的方法很多,不單單是系統呼叫,實際上系統呼叫是個不好的選擇,因為需要系統呼叫號,這個需要統一分配。
可以透過 ioctl 、 sysfs 、 proc 等來完成。

核心態和使用者態

當一個任務(程式)執行系統呼叫而陷入核心程式碼中執行時,我們就稱程式處於核心執行態(或簡稱為核心態)。此時處理器處於特權級最高的(0 級)核心程式碼中執行。當程式處於核心態時,執行的核心程式碼會使用當前程式的核心棧。每個程式都有自己的核心棧。當程式在執行使用者自己的程式碼時,則稱其處於使用者執行態(使用者態)。即此時處理器在特權級最低的(3 級)使用者程式碼中執行。當正在執行使用者程式而突然被中斷程式中斷時,此時使用者程式也可以象徵性地稱為處於程式的核心態。因為中斷處理程式將使用當前程式的核心棧。這與處於核心態的程式的狀態有些類似。

程式上下文和中斷上下文

處理器總處於以下狀態中的一種:
1 、核心態,執行於程式上下文,核心代表程式執行於核心空間;
2 、核心態,執行於中斷上下文,核心代表硬體執行於核心空間;
3 、使用者態,執行於使用者空間。
使用者空間的應用程式,透過系統呼叫,進入核心空間。這個時候使用者空間的程式要傳遞很多變數、引數的值給核心,核心態執行的時候也要儲存使用者程式的一些暫存器值、變數等。所謂的 “程式上下文”,可以看作是使用者程式傳遞給核心的這些引數以及核心要儲存的那一整套的變數和暫存器值和當時的環境等。
硬體透過觸發訊號,導致核心呼叫中斷處理程式,進入核心空間。這個過程中,硬體的一些變數和引數也要傳遞給核心,核心透過這些引數進行中斷處理。所謂的 “中斷上下文”,其實也可以看作就是硬體傳遞過來的這些引數和核心需要儲存的一些其他環境(主要是當前被打斷執行的程式環境)。