網路城邦
上一篇 回創作列表 下一篇   字體:
system call
2007/01/30 16:00:32瀏覽2942|回應2|推薦3
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, 都幫你寫好了.

注意事項:
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

( 休閒生活旅人手札 )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=keithmin&aid=699458

 回應文章

陳小春
等級:6
留言加入好友
在 uClinux 中實作 i2c
2007/01/31 19:02
http://macrossvin.blogspot.com/2006/09/uclinux-i2c.html

陳小春
等級:6
留言加入好友
分析原始碼的工具
2007/01/31 19:02
http://www.javaworld.com.tw/jute/post/print?bid=10&id=7353