環境版本: Gentoo 2007
核心版本: linux-2.6.28.5
硬體: x86
單核心CPU
各核心版本間大同小異, 但還是會稍有不同的部分, 例如檔案路徑更動, 或者 include 不同的標頭檔,
則需要另行上網查找資料或以 LXR 軟體搜尋 ; 另外, 不同的 Linux 系統之間指令可能會有所差異, 以下是一個簡單的 system call 範例.
步驟: 一. Kernel 設定
1. 註記 system call
2. 加上 systme call 的定義
3. 定義 system call 函式
4. 新增 system call 的實做
5. 設定 kernel/Makefile
6. 編譯核心, 安裝模組, 安裝核心
7. 重新開機
二. User 設定
1. 在 unistd.h 定義 system call
2. 在 syscall.h 定義 system call
3. 測試
一. kernel 部份
首先到要修改的 kernel 目錄下
ex: cd /usr/src/linux-2.6.28.5
1.
註記 system call
核心中有一份 table 用來註記 system call 的呼叫介面, 首先我們要再這裡新增 system call 名稱以及
unique ID:
( 路徑: arch/x86/kernel/syscall_table_32.S
或者 syscall_table_64.S , 視硬體而定 )
例: ......
.long sys_request_key
.long sys_keyctl
.long sys_hello < - 新增的system call

這裡的".long"是必須的, 它並不是代表回傳的型態, 而是 Linux
Assembly 的一個語法, 而所加的定義在檔案中的順序, 其實也就是這個 system call 的 system call number , 此例中的 number 是333
2. 加上 systme call 的定義
unistd_32.h 裡面會有一段跟 syscall_table_32.S 很像的
define , 不過在這裡 system call 是以"__NR_"開頭, 而其後跟著的數值則是用來代表它的
system call number
( 路徑: arch/x86/include/asm/unistd_32.h
)
( Ubuntu為: include/asm-generic/unistd.h
)
例: .......
#define __NR_pipe2 331
#define __NR_inotify_init1 332
#define __NR_hello 333
#ifdef __KERNEL__

3. 定義 system call 函式
( 路徑: arch/x86/include/asm/syscalls.h )
( Ubuntu為: include/linux/syscalls.h
)
例: .......
asmlinkage long sys_olduname(struct oldold_utsname
__user *);
asmlinkage int sys_hello(void);

4. 在 /kernel/ 目錄下新增 system call 的實作
例:
#include
#include
asmlinkage int sys_hello(void)
{
printk("hello system call!\n");
return 0;
}

( 值得注意的是, 檔名需跟 system call 名稱一樣, 如上例檔名就必須為 hello.c , 否則系統無法找到正確的 system call 對應 )
5. 設定 kernel/Makefile
接著將 system call 的實作檔放入
source code tree 中, 在 obj-y 後面加上自己新增要編譯的檔, 變數 obj-y 表示需要編繹到內核中的目標檔案名集合
例: ............
........... sys_ni.o hello.o <- span="">新增hello.o.->

6. 編譯核心, 安裝模組, 安裝核心
# make && make modules_install
&& make install
( Ubuntu為: # make bzImage
# make install )
7. 重新開機
( 這裡值得注意的是, 如果你的開機程式是使用 lilo 的話, 別忘記先更新 lilo 以後再重新開機, 否則開機的時候 lilo 會讀不到你剛剛編譯好的映象檔 ,如果使用的是 grub 則不需要 )
# /sbin/lilo <- lilo="" span="">更新->
# reboot
二、User 部分
核心編譯且安裝完成之後, 我們要修改一般程式 include 進來的檔( 路徑: /usr/include/ )
1.
在 unistd.h 定義 system call
在 asm/unistd.h
一樣加上 system call 的 define, 並且最底下的 NR_syscalls 必須要改成最大的 system call number 加 1
因為要讓 user 可以去呼叫 kernel 裡面的 system
call, 兩端的 system call number 必須相互對應, 以下是新增對應的 system call number
例:
#define __NR_vmsplice 316
#define __NR_hello 333
<- span="">新增->
#define NR_syscalls 334

2. bits/syscall.h 最後面加上自己的 define
例:
#define SYS_writev __NR_writev
#define SYS_helloy __NR_hello <- span="">新增的->

3. 最後, 我們寫個小程式來測式 system call 吧, 寫個 Test_Syscall.c
#include
#include
#include
#define __NR_hello 333
int hello(void)
{
return (int)
syscall(__NR_hello);
}
main()
{
printf("The return code
from the hello system call is %d\n", hello());
}
寫完之後, 幫這個檔案作編譯, 然後執行
# gcc Test_Syscal.c
# ./a.out
如果正確的話, 回傳值會是 0,
失敗的話會是-1, 如果正確, 我們就可以利用 dmesg 指令打開系統訊息查看結果, 可以看到 ”hello system call!” 的字串
# dmesg | tail –n 5

其實, 也可以寫的更簡單一點
#include
#include
#include
#define __NR_hello 333
main()
{
syscall(__NR_hello);
}
沒有留言:
張貼留言