參考文章:linux添加系統調用【簡單易懂】【含32位系統】【含64位系統】_64位 32位 系統調用-CSDN博客
安裝新內核
1. 在火狐下載你需要的版本的linux內核壓縮包
這里我因為在windows上面下載過,配置過共享文件夾,所以直接復制粘貼通過共享文件夾得到源碼。共享文件夾配置可以參考教程:VM Virtualbox虛擬機ubuntu共享文件夾 | 權限控制問題解決-CSDN博客
2. 在你下載的文件夾中打開終端
分別執行兩個語句
sudo -s
//申請權限
cp linux-5.4.293.tar.xz /usr/src
//將這個壓縮包拷貝至 /usr/src
在usr/src中成功找到!
在這里打開終端,對源碼進行解壓
sudo tar -xvf linux-5.4.293.tar.xz
sudo
:以超級用戶權限執行命令(需要輸入管理員密碼)tar
:Linux 下的歸檔工具-x
:解壓模式(extract)-v
:顯示詳細過程(verbose)-f
:指定文件名(file)
下面就得到了新內核!
給新內核添加一個新的系統調用
以下參考linux官方手冊:如何給linux-5.4添加一個系統調用Adding a New System Call — The Linux Kernel documentation
我最后一遍重新下載了linux 5.19的版本:
Index of /pub/linux/kernel/v5.x/
參考視頻[Linux Kernel] 系統調用的添加和測試(syscall;QEMU)_嗶哩嗶哩_bilibili
放在前面的友情提示:
這個虛擬機分配的內存一定要夠,我是分配了60G,最終源碼都是放在usr/src下面,最好保證編譯之前有30G左右的內存,不然會在你接近成功的時候發生“設備上沒有空間”的錯誤,功虧一簣!
報這個錯,再次打開虛擬機會發現虛擬機再也用不了了,只能重開
找一個文件夾,它的絕對路徑為:
/usr/src/linux-5.4.293/arch/x86/entry/syscalls
進去之后看這兩個文件,你的虛擬機的操作系統是32位就改syscall_32.tbl,64位就改syscall_64.tbl
不知道系統是多少位的?打開終端,輸入命令getconf LONG_BIT,看看你現在的操作系統中,long型數據占幾位,就知道系統是幾位的了
下面的部分就是修改內核源碼的部分了:
下面三張白色的圖是視頻里面的,用作參考,后面的圖是我自己修改的
?
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/sched/signal.h> // for for_each_process
#include <linux/uaccess.h> // for copy_to_user
#include <linux/printk.h>
#include <linux/errno.h>SYSCALL_DEFINE4(ps_info,int __user *, pid,char __user *, comm,long long __user *, ttime,long __user *, state)
{struct task_struct *task;int counter = 0;long ret;printk(KERN_INFO "[Syscall] ps_info invoked\n");printk(KERN_INFO "[StuID] ZhuoJunxi from CSU\n");for_each_process(task) {/* PID */ret = copy_to_user(&pid[counter],&task->pid,sizeof(task->pid));if (ret) return -EFAULT;/* Command name (fixed 16 bytes) */ret = copy_to_user(&comm[counter * TASK_COMM_LEN],task->comm,TASK_COMM_LEN);if (ret)return -EFAULT;/* Cumulative execution time */ret = copy_to_user(&ttime[counter],&task->se.sum_exec_runtime,sizeof(task->se.sum_exec_runtime));if (ret)return -EFAULT;/* Current state (renamed __state in 5.14+) */ret = copy_to_user(&state[counter],&task->__state,sizeof(task->__state));if (ret)return -EFAULT;counter++;}return 0;
}
修改完源碼之后,就要準備編譯了。
suso make mrpropersudo make clean?# 步驟1:編譯內核鏡像(bzImage)和模塊(modules)sudo make -j12? //這里的j是你分配給虛擬機的內核數量
make出現問題:由需要簽名證書部分交互的,或者說不存在XXX(這里我找不到bug圖片了)
解決方法:為 Linux 內核模塊簽名生成所需的證書和私鑰。
mkdir -p certs && openssl req -new -x509 -newkey rsa:4096 -keyout certs/signing_key.pem -out certs/signing_key.x509 -nodes -subj "/CN=Kernel Signing Key/"
這樣再重新運行make指令就好了,中間如果有一些bug是需要下載--直接下載
?
注意:只有出現最后一句 Kernel :? ? ? ?is ready 才是編譯成功的標志
否則就去上面找哪里有錯誤,一個個修正
編譯時間參考:15核CPU編譯一分鐘,4核CPU編譯兩小時
sudo make modules_install
sudo make install
?內核編譯好后,重啟虛擬機,輸入
uname -a
查看當前內核是否為你修改的那個內核,成功!?
測試程序?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>#define __NR_ps_info 451 // 根據實際系統調用號調整int main() {int pids[100];char comms[100 * 16];long long times[100];long states[100];int count = 100;// 調用 ps_info 系統調用syscall(__NR_ps_info, pids, comms, times, states, &count);printf("Retrieved %d processes\n", count);for (int i = 0; i < count && i < 10; i++) { // 只打印前10個進程printf("PID: %d, Comm: %s, Time: %lld, State: %ld\n",pids[i], &comms[i*16], times[i], states[i]);}return 0;
}
運行測試?