system call
2007/01/30 16:00
瀏覽3,002
迴響2
推薦3
引用0
Author: 陳炯廷
Subject: system call 一些注意的地方
--------------------------------------------------------------------------------
一點筆記給大家參考, 新增一個 system call 的步驟:
- 在 arch/i386/kernel/entry.S 新增一個 .long SYMBOL_NAME(sys_abc)
通常會加在最後面
- 在 include/asm/unistd.h 相對應的位置增加 __NR_abc
- 把 include/asm/unistd.h copy 到 /usr/include/asm 底下
- 在 include/linux/sys.h 的 NR_syscalls 的數值加一!! 這個步驟在網路上大部分的 tutorials 都沒有提及... 如果沒有加上的話, 且你的 system call 又加在最後一個, 那它會吃不到
接著就可以寫上妳的 system call, 看你要 append 到 kernel/xxx.c 裡頭, 或者是自己開一個新的目錄. 若是自己多寫一個檔案, 要注意 Makefile 要相對應的修改.
改好之後, 要開始製作 kernel, 詳細的"官方"說明在 /usr/src/linux/README 這個檔案看得到, 基本上的指令如下:
1. make mrproper
2. make menuconfig (或是同系列的都可以)
3. make dep
4. make modules
5. make modules_install
6. make
7. make install
第六步才是開始做 kernel, 這是我灌的方式, 和一般 Tutorial 寫的不大一樣。我發現 RedHat Enterprise 在
make install 的時候, 會自動產生 bzImage, 幫你做好 initrd, 而且還幫你將 grub 的設定都改好,
非常的方便。
1-5 的步驟, 只要在第一次 compile kernel 做就好了, 以後改好的每一次, 都只要做最後一個就可以了。 (因為最後一個會包含第六個)
編好 Kernel 之後請記得 REBOOT!
若是 System call 沒有跑起來, 有一個很簡單的方式可以 debug
以下是程式範例:
#include
_syscall0(int,hello);
int main() {
hello();
if (errno)
printf("%s\n", strerror(errno));
}
用 strerror 把 errno 印出來會有多一點點的錯誤訊息,
以 sys.h 沒有改來說, 它就會顯示 Function not implemented. 但如果你沒有用的話, 只會發現 hello 回傳 -1, 不方便 DEBUG.
另外, 我們所使用的 Kernel 版本, 在 task_struct 當中, 已經沒有 next_task和prev_task
這兩個東西了, 不過好消息是, 取而代之的變得更好使用。這個版本的 kernel 直接將 next_task 和 prev_task 定義成
macro,
只要 next_task(p), 它就丟給你 p 下一個的 task_struct, 都幫你寫好了.
http://fossil.wpi.edu/docs/howto_add_systemcall.html
Subject: system call 一些注意的地方
--------------------------------------------------------------------------------
一點筆記給大家參考, 新增一個 system call 的步驟:
- 在 arch/i386/kernel/entry.S 新增一個 .long SYMBOL_NAME(sys_abc)
通常會加在最後面
- 在 include/asm/unistd.h 相對應的位置增加 __NR_abc
- 把 include/asm/unistd.h copy 到 /usr/include/asm 底下
- 在 include/linux/sys.h 的 NR_syscalls 的數值加一!! 這個步驟在網路上大部分的 tutorials 都沒有提及... 如果沒有加上的話, 且你的 system call 又加在最後一個, 那它會吃不到
接著就可以寫上妳的 system call, 看你要 append 到 kernel/xxx.c 裡頭, 或者是自己開一個新的目錄. 若是自己多寫一個檔案, 要注意 Makefile 要相對應的修改.
改好之後, 要開始製作 kernel, 詳細的"官方"說明在 /usr/src/linux/README 這個檔案看得到, 基本上的指令如下:
1. make mrproper
2. make menuconfig (或是同系列的都可以)
3. make dep
4. make modules
5. make modules_install
6. make
7. make install
第六步才是開始做 kernel, 這是我灌的方式, 和一般 Tutorial 寫的不大一樣。我發現 RedHat Enterprise 在
make install 的時候, 會自動產生 bzImage, 幫你做好 initrd, 而且還幫你將 grub 的設定都改好,
非常的方便。
1-5 的步驟, 只要在第一次 compile kernel 做就好了, 以後改好的每一次, 都只要做最後一個就可以了。 (因為最後一個會包含第六個)
編好 Kernel 之後請記得 REBOOT!
若是 System call 沒有跑起來, 有一個很簡單的方式可以 debug
以下是程式範例:
#include
_syscall0(int,hello);
int main() {
hello();
if (errno)
printf("%s\n", strerror(errno));
}
用 strerror 把 errno 印出來會有多一點點的錯誤訊息,
以 sys.h 沒有改來說, 它就會顯示 Function not implemented. 但如果你沒有用的話, 只會發現 hello 回傳 -1, 不方便 DEBUG.
另外, 我們所使用的 Kernel 版本, 在 task_struct 當中, 已經沒有 next_task和prev_task
這兩個東西了, 不過好消息是, 取而代之的變得更好使用。這個版本的 kernel 直接將 next_task 和 prev_task 定義成
macro,
只要 next_task(p), 它就丟給你 p 下一個的 task_struct, 都幫你寫好了.
注意事項:
1. 文中的 NEW 請自行統一置換成自訂的名稱,但是該有的
sys_ 或者 __NR_ 請務必保留
2. 關於 一、2 的 define 值,建議不要跳號,由原本的最
後值往上 +1 。 (至少在我實驗後,跳號會造成失敗)
而 /usr/include 的 define (即 二、1) 則根據 一、2
的值,與之相同。
3. 關於 三、 的部分,如果發生 Segmentation fault 或錯
誤的情況,建議至 source code 下 make clean 後依完
整的核心編譯方式,重新編譯並重開機再試一次。
一、在 linux source code 的部份(/usr/src/linux/)
1. arch/i386/kernel/entry.S 的最後面加上要新增的 system call
名稱,例:
.long sys_request_key
.long sys_keyctl
.long sys_NEW (新增的system call)
若是在 2.6.12 之後的kernel,他會把這個部份獨立出來放在
syscall_table.S 裡面
2. include/asm-i386/unistd.h 裡面加上自己的 define,例:
#define __NR_request_key 287
#define __NR_keyctl 288
#define __NR_NEW 289 (新增的)
#define NR_syscalls 290 (改成最後一個define的數字加1)
3. include/linux/syscalls.h 裡面加上函式的定義,例:
asmlinkage long sys_NEW(int arg1, int arg2);
4. kernel/ 裡面新增或在隨便一個檔案裡面加上 system call的實作
例:新增一個 NEW.c
內容:
#include <linux/syscalls.h>
#include <linux/errno.h>
asmlinkage long sys_NEW(int arg1, int arg2)
{
// your implementation code
return (arg1 + arg2);
}
5. kernel/Makefile
在 obj-y 後面加上自己新增要編譯的檔 (NEW.c -> NEW.o)
二、修改一般程式 include 進來的檔(/usr/include/)
1. asm-i386/unistd.h一樣加上自己的 define,例:
#define __NR_sys_kexec_load 283
#define __NR_NEW 289 (新增的)
#define NR_syscalls 290 (最後一個define的數字加上1)
2. bits/syscall.h 最後面加上自己的 define,例:
#define SYS_writev __NR_writev
#define SYS_NEW __NR_NEW (新增的)
三、make ; make modules_install
四、寫個小程式測式一下吧,例:
#include <linux/unistd.h>
#include <errno.h>
static inline _syscall2(long, NEW, int, arg1, int, arg2);
/* linux中一共定義了7種不同的_syscall*,在 unistd.h 裡面
可以看到,若定義 system call 有要傳參數的話必需使用別
的 _syscall
*/
int main()
{
printf("%d\n", NEW(10, 20) );
return 0;
}
五、test
gcc test.c
./a.out
==> 30
http://fossil.wpi.edu/docs/howto_add_systemcall.html
你可能會有興趣的文章: