實驗一:Linux核心編譯及添加系統調用
一、實驗目的
- 了解Linux系統處理系統調用的流程
- 增加一個系統調用
二、實驗内容
- nice,可以了解為謙讓度,CPU在選擇程序時根據優先級prio選擇,當nice值越高,可了解為這個程序越是謙讓,即優先級越低
-
添加一個系統調用,實作對指定程序的nice值的修改或讀取功能,并傳回系最新的nice值,即優先級prio。
建議調用原型為:
Int mysetnice(pid_t pid, int flag, int nicevalue,void_userprio,void_usernice)
參數含義:
pid:程序ID
flag:若值為0,表示讀取nice值;若值為1表示修改nice值。
prio,nice:指向程序目前優先級及nice值。
傳回值:系統調用成功時傳回0,失敗時傳回錯誤碼EFAULT。
- 寫一個簡單的應用程式測試系統調用
- 深入閱讀相關函數源碼
三、流程圖
四、具體實作
-
安裝虛拟機及ubuntu
按指導來問題不大,在可行前提下,配置設定處理器選擇4核或以上
大小配置設定60G左右!
https://jingyan.baidu.com/article/f96699bb147a73894e3c1b2e.html
-
開啟系統,打開terminal,進入管理者模式
打開termintal: ctrl+alt+t
管理者模式: 輸入 sudo su 輸入使用者密碼進入管理者模式
-
下載下傳解壓核心
下載下傳核心: 輸入 wget http://mirrors.ustc.edu.cn/kernel.org/linux/kernel/v4.x/linux-4.4.196.tar.xz
解壓核心: 輸入 tar -xvJf linux-4.4.196.tar.xz
-
系統調用
裝各種包 輸入 sudo apt-get install vim libncurses5-dev make openssl libssl-dev bison flex ctags
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP31EMRR1TzkkeNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2ADNzEzNzITM5EDMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
添加系統調用号 進入核心:cd linux-4.4.196 # 之後的操作都是在這個目錄下
編輯調用表:vim arch/x86/entry/syscalls/syscall_64.tbl
輸入G (跳末行)上行到300多行 ,輸入i (進入編輯模式)
輸入如圖
按ESC鍵 退出編輯模式 輸入 :wq 儲存并退出
申明系統調用 vim include/linux/syscalls.h
輸入 G i 添加如下
按ESC鍵 退出編輯模式 輸入 :wq 儲存并退出
實作調用 vim kernel/sys.c
輸入 G i 添加如下
SYSCALL_DEFINE5 (mysetnice,pid_t,pid,int,flag,int,nicevalue,void __user*,prio,void __user*,nice){
//SYSCALL_DEFINEN中N表示系統調用所需要的參數個數,我們的是5個
struct task_struct *p;//程序結構體指針
struct pid *id;//pid結構體
int m,n;
id=find_get_pid(pid);//通過傳入的pid_t pid得到id結構體
p=pid_task(id,PIDTYPE_PID);//通過id得到指定程序,PIDTYPE_PID指的是程序類型的pid
m=task_nice(p); //通過p得到nice值
n=task_prio(p); //通過p得到prio值(優先級)
if(flag==0){//讀取
copy_to_user(nice,(void*)&m,sizeof(m));//将m的位址強轉為void *類型
copy_to_user(prio,(void*)&n,sizeof(n));
return 0;
}
else if(flag==1){//修改
printk("nice value before modified:%d\n",m);
set_user_nice(p,nicevalue);//修改nice的值
return 0;
}
printk("syscall failed!");
return EFAULT;
}
按ESC鍵 退出編輯模式 輸入 :wq 儲存并退出
-
配置編譯核心
輸入 make mrproper
輸入 make clean
輸入 make menuconfig
(terminal視窗最大化)
選擇Save 回車确定 回車确定 選擇Exit
輸入 make -j4
(-j4表示4線程編譯,耗費較長,無視warning,跳出error可以ctrl+c結束了,出錯了就沒必要再編譯了,看看是否漏掉步驟,根據跳出的error解決)
-
安裝核心重新開機系統
輸入 make modules
輸入 make modules_install
輸入 make install
輸入 update-grub2
輸入 reboot
重新開機後 ctrl+alt+t 打開terminal 輸入 sudo su 進入管理者模式
輸入 uname -a 如果顯示的是下載下傳的核心 這裡是4.4.196 表明編譯成功
-
編寫函數測試用
輸入 vim exp_1_test.c 建立C檔案測試調用
輸入i (進入編輯模式)
編寫代碼如下
#include<stdio.h> #include<unistd.h> #include<sys/syscall.h> #define __NR_mysyscall 326 int main(){ int nice,prio; pid_t id; id=getpid(); printf("----------------read-----------------\n\n"); syscall(__NR_mysyscall,id,0,NULL,&prio,&nice); printf("before modified:pid:%d,prio:%d,nice:%d\r\n",id,prio,nice); printf("-----------------set-------------------\n\n"); printf("syscall(__NR_mysyscall,id,1,-8,&prio,&nice);\n"); syscall(__NR_mysyscall,id,1,-8,&prio,&nice); printf("------------------read-----------------\n\n"); syscall(__NR_mysyscall,id,0,NULL,&prio,&nice); printf("modified:pid:%d,prio:%d,nice:%d\r\n",id,prio,nice); return 0; }
按ESC鍵 退出編輯模式 輸入 :wq 儲存并退出
輸入 gcc exp_1_test.c 編譯C檔案
輸入 ./a.out 檢視結果
-
相關核心源碼閱讀
輸入 cd linux-4.4.196 進入目錄
輸入 sudo ctags -R * (一些準備工作)
輸入 vim kernel/sys.c 就是之前實作調用的
這裡以檢視set_user_nice函數及nice定義為例,可以此類推
這裡光标移動到如圖 set_user_nice 函數
輸入 ctrl + ] 進入函數 (退出則是c trl +T)
顯示如圖
光标移動到 MIN_NICE 輸入 ctrl + ] 進入
顯示如圖