[保姆級教程] 如何在 Linux Kernel (V5.17.7) 中新增一個系統呼叫(System call)

aalanwyr 發表於 2022-05-15
Linux

    最近在學習 《linux Kernel Development》,本書用的linux kernel 是v2.6 版本的。看完”系統呼叫“一節後,想嘗試新增一個系統呼叫,然後重編一個kernel。經過幾個小時的嘗試,實現了這個小功能,其中也遇到了不少坑,本文主要是記錄分享下如何在Linux Kernel (V5.17.7) 中新增一個系統呼叫(System call)。

     編kernel之前需要注意:

               1、修改的kernel是目前最新的release 版本(V5.17.7), 書中v2.6版本的kernel太老了,gcc需要降到4.8版本,否則無法編過。 kernel 釋出地址:https://www.kernel.org/

               2、需要選用大記憶體,多核的機器編kernel,否則會出現各種異常問題,而且編kernel 很費時間。15GB記憶體的機器,編不過kernel。換用100GB記憶體的機器就好了😅

    本文主要包含以下幾點內容:

               1、環境準備

               2、修改kernel

               3、rebuild kernel 以及安裝kernel

               4、測試結果

1、環境準備

     我編kernel的機器是:Ubuntu 20.04.1 LTS,記憶體180GB,  cores: 88

1.1 更新系統的源

sudo apt update && sudo apt upgrade -y

1.2 安裝編譯kernel 需要的依賴

sudo apt install build-essential libncurses-dev libssl-dev libelf-dev bison flex -y

我這裡用的vim,沒有的話也需要安裝:

sudo apt install vim -y

1.3 清除已經安裝的packages

sudo apt clean && sudo apt autoremove -y

1.4 下載kernel code

wget -P ~/ https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.17.7.tar.xz
tar -xvf ~/linux-5.17.7.tar.xz -C ~/

2、修改kernel

2.1 檢查你自己當前系統的kernel 版本

uname -r

5.11.0-36-generic

重新安裝kernel之後,這個版本號會被修改。

2.2 切換到工作目錄中,然後建立自己的系統呼叫

cd ~/linux-5.17.7/
mkdir hello

 2.3 建立自己的系統呼叫

vim hello/hello.c

 新增程式碼。

#include <linux/kernel.h>
#include <linux/syscalls.h>

SYSCALL_DEFINE0(hello)

{
    printk("hello_system_call.\n");
    return 0;
}

 2.4 為你的系統呼叫建立 Makefile

vim hello/Makefile

 新增下面內容:

obj-y := hello.o

 2.5 將你的系統呼叫新增到Kernel 的makefile中

vim Makefile

 搜尋 core-y, 完成如下新增:

 [保姆級教程] 如何在 Linux Kernel (V5.17.7) 中新增一個系統呼叫(System call)

 2.6 將系統呼叫的相應函式原型新增到系統呼叫的標頭檔案中

vim include/linux/syscalls.h

新增:

asmlinkage long sys_hello(void);

[保姆級教程] 如何在 Linux Kernel (V5.17.7) 中新增一個系統呼叫(System call)

2.7 在system_table 中為你的系統呼叫開闢一個新的系統呼叫號。

vim arch/x86/entry/syscalls/syscall_64.tbl

 [保姆級教程] 如何在 Linux Kernel (V5.17.7) 中新增一個系統呼叫(System call)

3、編譯kernel 並安裝

    前面的步驟都很簡單,這一步可能會出現各種問題,而且很耗時。

3.1 建立你的.config

    這裡一路預設設定就好。

make menuconfig

3.2 查詢你的機器logicl cores 有多少個

nproc

3.3 編譯安裝你的kernel

make -j32
echo $?  // make 結束之後記得檢查一下 狀態
###if output is 0 then
sudo make modules_install -j32
echo $? 
make install -j32

3.4 檢視kernel 是否安裝進去了

sudo update-grub
sudo reboot

 [保姆級教程] 如何在 Linux Kernel (V5.17.7) 中新增一個系統呼叫(System call)

4、測試結果

4.1 首先check 你的kernel 換好沒

uname -r

4.2 編一個code 呼叫你的系統呼叫

  由於系統呼叫不像普通函式那樣,需要通過sys_call 以及系統呼叫號才能實現系統呼叫。建立一個test.c

#include <linux/kernel.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define __NR_hello 451

long hello_syscall(void)
{
    return syscall(__NR_hello);
}
int main(int argc, char *argv[])
{
    long activity;
    activity = hello_syscall();
    if(activity < 0)
    {
        perror("Sorry, xxx. Your system call appears to have failed.");
    }
    else
    {
        printf("Congratulations, xxx! Your system call is functional. Run the command dmesg in the terminal and find out!\n");
    }
    return 0;
}

4.3 測試結果

gcc -o test test.c
./test
dmesg // 後面也能看到系統呼叫列印的資訊

 Congratulations, yaran! Your system call is functional. Run the command dmesg in the terminal and find out!