[保姆級教程] 如何在 Linux Kernel (V5.17.7) 中添加一個系統調用(System call)

    最近在學習 《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 發佈地址://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 ~/ //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, 完成如下添加:

 

 2.6 將系統調用的相應函數原型添加到系統調用的頭文件中

vim include/linux/syscalls.h

添加:

asmlinkage long sys_hello(void);

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

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

 

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

 

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!

Tags: