How to Add a System Call
Kernel : 2.6.18
編譯環境 : Fedora Core 6
假設要加的system call為 sys_project, 有一個int的輸入參數
一、在linux source code的部份(以 linux 代表source code的根目錄)
- linux/arch/i386/kernel/syscall_table.S的最後面加上要新增的system call名稱
如果syscall_table.S的最後面長得像這樣.那麼要加入sys_project就要把它改成這樣, 這裡的".long"是必須的, 它並不是代表回傳的型態, 而是Linux Assembly的一個語法
.
.long sys_tee /* 315 */
.long sys_vmsplice
.long sys_move_pages
.而所加的定義在檔案中的順序, 其實也就是這個system call的system call number, 此例中是318
.
.long sys_tee /* 315 */
.long sys_vmsplice
.long sys_move_pages
.long sys_project /* 318 */ - linux/include/asm/unistd.h裡面加上自己的define
unistd.h裡面會有一段跟syscall_table.S很像的define, 不過在這裡system call是以"__NR_"開頭, 而其後跟著的數值則是system call number, 如果在它定義的最後一個system call附近像這樣.因為 NR_syscalls 的值必須等於最大的system call加 1, 所以在根據syscall_table.S中的順序修改unistd.h之後, 不要忘了修改NR_syscalls的值
.
#define __NR_vmsplice 316
#define __NR_move_pages 317
#ifdef __KERNEL__
#define NR_syscalls 318
.
.
.
.
#define __NR_vmsplice 316
#define __NR_move_pages 317
#define __NR_project 318
#ifdef __KERNEL__
#define NR_syscalls 319
.
. - linux/include/linux/syscalls.h裡面加上函式的定義
函式定義前面必須加上asmlinkage以確保編譯時連結的正確性, 所以加完後的狀況大概像這樣.
.
asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
size_t len);
asmlinkage long sys_project( int i );
#endif - 將system call的實作檔放入source code tree中
原則上, 實作檔應該根據 syscall 的類型放在相對應的資料夾中, 然後再將實作檔編譯後的.o檔檔名加入該資料夾下的Makefile的obj-y之中, 假設實作檔的source code為project.c, 放在linux/kernel/, 那linux/kernel/Makefile改完後大概長這樣.而在撰寫實作檔的時候, 請記得將"#include <linux/linkage.h>"加進去, 否則編譯將會發生問題, 以下是一個實作檔的範例
.
obj-y = project.o sched.o fork.o exec_domain.o panic.o printk.o profile.o \
.
.project.c
#ifndef __LINUX_PROJECT
#define __LINUX_PROJECT
#include <linux/linkage.h>
#include <linux/kernel.h>
asmlinkage long sys_project( int i ){
printk( "Success!! -- %d\n", i );
return 0;
}
#endif - 在/usr/include/asm/unistd.h中加入定義讓User能呼叫
其實在上一步驟整個system call已經算是加好了, 但此時User只能以system call number呼叫(此例中是318), 為了讓User能以system call的名字呼叫, 所以要修改/usr/include/asm/unistd.h,改完結果像這樣.
.
#define __NR_vmsplice 316
#define __NR_move_pages 317
#define __NR_project 318
#endif /* _ASM_I386_UNISTD_H_ */ - 重新編譯Kernel---->大功告成!!!
二、如何呼叫System call
要呼叫system call, 必須加入"#include<syscall.h>", 並以syscall( __NR_[system call的名字], [參數1, 參數2,...] )來呼叫, 如果沒有做步驟 5, 則必須以syscall( [system call number], [參數1, 參數2,...] )來呼叫, 以下是一個範例
#include<syscall.h>
int main(){
syscall( __NR_project, 2 );
/* 如果沒有做步驟 5, 就用syscall( 318, 2 ); 代替 */
return 0;
}
執行結果
[root@localhost test]# ./a.out
[root@localhost test]# dmesg
.
.
.
Success!! -- 2
[root@localhost test]#
---------
linux/include/linux/syscalls.h
task_struct
asmlinkage long sys_project(char *test_array,char *test_array_tail,int operation);
----------
How to Add a System Call
假設要加的system call為 sys_project, 有一個int的輸入參數
注意有些地方該是sys_開頭(syscalls.h)
In source code 的根目錄:
arch/i386/kernel/syscall_table.S
include/asm-i386/unistd.h
include/linux/syscalls.h
kernel/Makefile
系統根目錄
/usr/include/asm/unistd.h
來源:
http://adl.csie.ncu.edu.tw/~ernieshu/syscall_2_6_35.htm
http://adl.csie.ncu.edu.tw/~ernieshu/syscall.htm