操做系統-Linux添加系統調用

Linux添加系統調用

分享一下從編譯內核到Linux添加系統調用的過程吧。linux

1、準備

我使用的是ubuntu 16.04 LTS,下載的是4.4.25的內核。
首先要注意硬盤至少須要30g,否則會爆掉...別問我怎麼知道的。內存分配的稍微大點就好。ubuntu

內核下載地址瀏覽器

2、編譯內核

編譯內核其實很簡單~測試

咱們先切換到root用戶,把下載好的內核壓縮文件放到/usr/src下,而後進入這個目錄解壓ui

xz -d linux-4.4.25.tar.xz
tar -xvf linux-4.4.25.tar

而後若是不是第一次編譯或者編譯出錯須要從新編譯最好都執行一下make mrproper
執行這條命令須要先安裝一個包es5

apt-get install libncurses5-dev

咱們是剛下載的的乾淨的內核源碼包,因此不用執行make mrproper這條命令。firefox

make mrproper -Remove all generated files + config + various back files

make clean - Remove most generated files but keep the config and enough build support to build external modules

因此咱們能夠知道make mrproper和make clean的區別主要就是前者會刪除全部的編譯生成文件,然後者會保留配置文件.config,還有足夠的擴展模塊的支持。因此其實想清除編譯殘留數據的話執行make clean就能夠了。實際上make mrproper一開始就會調用make clean的。code

好了 下面咱們要配置內核選項了進程

make menuconfig

這個就去網上找具體點的吧 選項太多
會出來一個圖形界面 配置好exit會提示save便可。內存


以後就是激動人心的編譯內核時刻
咱們先安裝一個包

apt-get install libssl-dev

生成啓動映像文件

make bzImage

而後去看個番什麼的等吧 不過可能要多看幾集

編譯完成以後繼續編譯模塊

make  modules

注意咱們一直是在/usr/src/linux-4.4.25這個文件夾下操做的,此次時間就更長了。個人配置通常i5並且是虛擬機,加上編譯內核一共可能要幾個小時,因此去打會球吧=。=

模塊編譯好以後的步驟都很快了,
安裝模塊

make modules_install

而後要創建載入虛擬內存盤的編在內核中的根文件系統鏡像

mkinitramfs 4.4.25 -o /boot/initrd-4.4.25.img

配置grub引導

update-grub2

最後重啓系統就大功告成了

reboot

最後能夠經過uname -a查看內核版本

3、添加新的系統調用

1.分配系統調用號
先去查看一下系統的調用號使用到多少了,查找一下系統調用表
/usr/src/linux-4.4.25/arch/x86/entry/syscalls/syscall_64.tbl
個人版本使用到了325,因此我新的系統調用用326號。注意文件裏要看屬於x64的系統調用號。
而後咱們修改/usr/include/asm-generic/unistd.h設置系統調用號
添加

#define __NR_saulcall 326
  __SYSYCALL(__NR_saulcall,sys_saulcall)

而且將後面的__NR_syscalls的號加1。

ps: 起名困難症 不過一看到call就想起better call saul~ 就用了這個

2.修改系統調用表,關聯調用號與調用的服務例程地址
/usr/src/linux-4.4.25/arch/x86/entry/syscalls/syscall_64.tbl

326       64        saulcall   sys_saulcall

3.編寫服務例程
要爲咱們的服務寫程序了
/usr/src/linux-4.4.25/kernel/sys.c
我這裏是一個簡單的實現讀取進程的nice值和修改進程nice值的服務
參數flag爲1時修改nice
參數爲0時讀取nice

SYSCALL_DEFINE3(saulcall, pid_t, pid, int, flag, int, nicevalue){    
    int error = 0;
    struct task_struct *p;
    for(p = &init_task;(p = next_task(p)) != &init_task;){    
        if(p->pid == pid){
            if(flag == 0){
                printk("the process's nice = %d",task_nice(p));
            } else if(flag == 1){
                printk("the process changed to %d",nicevalue);
                set_user_nice(p,nicevalue);
            } else {
                error = -EFAULT;
            }
            return error;
        }
    }
    error = -EFAULT;
    return error;
}

SYSCALL_DEFINE3的3即爲參數個數,其餘就不過多解釋了,程序輕噴....

4.從新編譯內核
不從新編譯沒法生效...等吧=。=

5.編寫用戶態程序測試
下面就能夠寫程序測試啦
得引入下頭文件

#include <linux/unistd.h>
#include <sys/syscall.h>

而後能夠選擇一個進程調用咱們的服務修改或者讀取nice值啦,
因爲使用了printk,咱們要用dmesg查看輸出信息。
可使用top -p pid查看指定進程的信息。

提供一個小demo:
首先咱們能夠查找一個指定進程的pid,能夠用pgrep加指定進程名,
也能夠用top命令顯示各個進程資源佔用,而後找一個進程的pid來實驗咱們的系統調用,比方說我先打開火狐瀏覽器,而後假設用top命令看到firefox的pid爲4325,程序就能夠以下來寫

#include <linux/unistd.h>
#include <sys/syscall.h>
int main()
{
    syscall(__NR_saulcall,4325,1,15); // 修改4325進程的nice值爲15
    return 0;
}

再次使用Top查看firefox進程的nice值能夠看到已經被更改爲咱們想要的數值。

over.

相關文章
相關標籤/搜索