給linux新增系統呼叫 從源頭說起

2021-06-28 10:53:29 字數 2940 閱讀 1728

給linux新增系統呼叫,網上一搜一大堆,我很久之前也試圖新增過並且按照網上的教程一步一步做,但是都沒有成功過,因為網上的教程大體都是乙個樣子,乙份創造多分副本,照著做也不明白為什麼,而且linux核心版本從2.6跨越到3.x之後的目錄結構的差異也比較大,同一種方法在另乙個核心中不見得就能夠行得通。本文講解的核心採用的linux2.6.32.63版本。

本文試圖從系統呼叫的概念入手,然後再來新增系統呼叫。理解了這個原理遠比照著教程做出效果來卻不知其所以然更重要。

linux通過int 0x80指令產生中斷,核心會查詢中斷向量表來執行相應的中斷函式。在中斷函式中核心通過查詢函式指標陣列,取出下標為%eax的指標元素並執行,這就是系統呼叫的主要步驟。

int 0x80是一條彙編指令,通常用在內聯彙編中,如(參見《程式設計師的自我修養》第四章:最小的程式):

char *str = "hello world!\n";

asm( "movl $13, %%edx \n\t"

"movl %0, %%ecx \n\t"

"movl $1, %%ebx \n\t"

"movl $4, %%eax \n\t"

"int $0x80 \n\t"

::"r"(str): "edx", "ecx", "ebx");

上面的**實現了write的系統呼叫,當執行到int 0x80的時候產生中斷,中斷函式執行4號系統呼叫,在32位系統上該函式為sys_write(),它有三個引數,分別是%ebx、%ecx、%edx,它們的值是1、str、13,這樣核心執行的函式就是sys_write(1, str, 13)。即向標準輸出檔案寫str,執行後我們會在螢幕上面看到"hello world"的字樣。

這樣看來是不是很簡單?

x86的中斷向量表在linux原始碼的arch/x86/kernel/traps.c裡可見一部分,函式trap_init()用於初始化中斷向量表,在它的末尾可以看到:

函式set_system_trap_gate用於設定某個中斷號上的處理程式,在該函式中還有其他幾種設定方式,這些方式適用範圍也不一樣,這裡我們關心的是syscall_vector和system_call這兩個符號。在arch/x86/include/asm/irq_vectors.h中可以找到:

可以知道0x80號中斷執行的函式就是system_call,在arch/x86/kernel/entry_64.s我找到了該函式的入口(32位路徑為arch/x86kernel/entry_32.s):

可以看到截圖倒數第二行:call *sys_call_table(,%rax,8) 這條指令的意思就是call *(sys_call_table+8*%rax)。sys_call_table是乙個函式指標陣列,每個指標佔8位,取其中第%rax個指標並執行。這就是我們使用者態所謂的中斷呼叫號,上例中我們的中斷呼叫號是4,在32位系統上是sys_write的系統呼叫。

sys_call_table陣列定義在檔案arch/x86/kernel/syscall_64.c中,其定義如下:

很明顯這是個指標陣列,它的賦值方式很特別,舉個例子:

type_t array[arraysize + 1] = ;

結果中的0和1元素會被覆蓋,其他的元素都是element。這樣的語法在c++是不支援的。我們看看#include 裡面有什麼:

將上圖中的巨集展開後得到和上例形式相同的陣列,這兩張圖裡面用到了很多的巨集定義,讀者可以留心觀察一番。最終sys_call_table陣列就包含了該檔案所列舉的所有系統呼叫函式。細心的讀者肯定已經發現了這個陣列的大小__nr_systcall_max+1了,我們新增系統呼叫並不需要改動這個值,看看它的定義arch/x86/kernel/asm-offsets_64.c:

所以sys_call_table陣列的大小就是#include 裡面的函式的個數,如果需要新增自己的函式在這個標頭檔案新增即可。細心的讀者已經發現我上圖在末尾新增的自己的函式。到這裡基本上就大功告成了,讀者們可以理一理思路。

剩下的工作就是宣告並定義我們新增的函式。核心提供了乙個巨集定義來定義系統呼叫syscall_definex(),我們只需要是用這個巨集來定義自己的系統呼叫。定義的位置最好跟你的函式實現的功能關聯,比如你要實現檔案讀寫相關的功能那麼你可以定義在fs/open.c等檔案中,下面是我的定義fs/open.c:

系統呼叫的宣告在include/linux/syscalls.h:

編譯安裝核心(網上的方法很多可以參考網上的最後可以執行make modules_install install來完成自動安裝)。

安裝完畢!

測試使用者態程式:

成功新增,讀者可以在此基礎上新增更多的功能。

linux 新增系統呼叫

此文於2010 02 26被推薦到csdn首頁 如何被推薦?新的建立檔案描述符的 syscall 一般都支援額外的 flags 引數,可以直接指定 o nonblock 和 fd cloexec,例如 以上 6 個 syscalls,除了最後乙個是新功能,其餘的都是增強原有的呼叫,把數字尾號去掉就是...

Linux新增系統呼叫

修改核心 新增函式,新增函式宣告以及新增系統呼叫id,來實現給自己編譯的核心新增系統呼叫。當然這個過程是在編譯核心之前完成的,核心編譯過程請參照linux核心編譯 進入解壓的檔案目錄 cd usr src linux 5.1 kernel在sys.c中新增函式 執行vim sys.c使用vim開啟s...

Linux新增系統呼叫

通常新增系統呼叫有兩種方案 重新編譯核心 新增核心模組 此處我們採用重新編譯核心的方式增加系統呼叫。實驗環境 x86 64 gnu linux 4.15.0 ubuntu18.04 將其拷貝到 usr src目錄下 cp linux 4.19.1.tar.xz usr src 解壓縮並鏈結 xz c...