MIPS Linux 下新增系統呼叫,以Linux kernel 2.6.18為例.

Wenxy1發表於2009-11-20

 MIPS Linux 下新增系統呼叫,以Linux kernel 2.6.18為例

新增一個系統呼叫有以下幾個步驟:
1.  在 kernel 的系統呼叫表 sys_call_table 中新增你的系統呼叫入口

根據你用的核心位數(32/64bit) 選擇需要修改的檔案:
arch/mips/kernel/scall32-o32.S  ------> 32bit kernel
arch/mips/kernel/scall64-64.S   ------> 64bit kernel

64bit核心,如果支援相容32 bit ABI (o32, n32 ) 則還需修改 scall64-o32.S 或 scall64-n32.S
以32bit 核心為例,在 arch/mips/kernel/scall32-o32.S  中找到巨集定義

  .macro  syscalltable          /* 系統呼叫號從 4000 開始 */
    ......
    ......
    sys    sys_faccessat        3    /* 4300 */
    sys    sys_pselect6        6
    sys    sys_ppoll        5
    sys    sys_unshare        1
    sys    sys_splice        4
    sys    sys_sync_file_range    7    /* 4305 */
    sys    sys_tee            4
    sys    sys_vmsplice        4
    sys    sys_move_pages        6
    sys    sys_set_robust_list    2
    sys    sys_get_robust_list    3    /* 4310 */
    sys    sys_ni_syscall        0
    sys    sys_ni_syscall        0
    sys    sys_ni_syscall        0
    sys    sys_ioprio_set        3
    sys    sys_ioprio_get        2    /* 4315 */
    sys sys_wenxy_test        0    /* system call ID is 4316, wenxy add, 20091120 */
    .endm
......    

最後加入自定義的系統呼叫 sys_wenxy_test 於 sys_call_table 中, sys 為輔助巨集,呼叫名後的數值 0 指示該系統呼叫所需的引數個數。

只能加在 sys_call_table 的最後,否則會擾亂標準的系統呼叫。


2. 實現系統呼叫

可以在 arch/mips/kernel/syscall.c 中給出一個實現,如:
......
/* wenxy add begin, 20091119, a.m. */
#include "/opt/bcm97405/kernel/stblinux-2.6.18/arch/mips/sibyte/cfe/cfe_api.h"
asmlinkage int sys_wenxy_test(void)
{
    uint64_t cfe_ept, cfe_handle;
    int n;
    //n = cfe_init(cfe_handle, cfe_ept);
    
    printk(KERN_EMERG "kernel, wenxy debug:    into [%s], call [%s()]/n", __FILE__, __FUNCTION__);
    return 100;
}
/* wenxy add end */


3. 修改 include/asm-mips/unistd.h

根據你的核心位和支援的ABI版本修改相應的巨集定義,32bit 核心需修改:

#define __NR_Linux_syscalls         320    ---------> 321    (The number of linux syscalls)
#define __NR_O32_Linux_syscalls     320  ---------> 321      (The number of linux O32 syscalls)

相應的在其上的巨集集的最後加入:
.......
#define __NR_ppoll            (__NR_Linux + 302)
#define __NR_unshare            (__NR_Linux + 303)
#define __NR_splice            (__NR_Linux + 304)
#define __NR_sync_file_range        (__NR_Linux + 305)
#define __NR_tee            (__NR_Linux + 306)
#define __NR_vmsplice            (__NR_Linux + 307)
#define __NR_move_pages            (__NR_Linux + 308)
#define __NR_set_robust_list        (__NR_Linux + 309)
#define __NR_get_robust_list        (__NR_Linux + 310)
#define __NR_ioprio_set            (__NR_Linux + 314)
#define __NR_ioprio_get            (__NR_Linux + 315)

/* wenxy add begin , 20091119, a.m. */
#define __NR_wenxy_test        (__NR_Linux + 316)
/* wenxy add end */

......



4. 測試新的系統呼叫wenxy_test
test.c檔案, C程式:
#if 1
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#else
#include "/opt/bcm97405/kernel/stblinux-2.6.18/include/linux/unistd.h"
#include "/opt/bcm97405/kernel/stblinux-2.6.18/include/sys/syscall.h"
#endif


//#define __NR_getjiffies        320
//#define __NR_wenxy_test        319
#define __NR_wenxy_test    (__NR_Linux + 316)

_syscall0(int, wenxy_test);

int main()
{
  long jiffies;
    int n;
//  jiffies = syscall( __NR_getjiffies );

//  printf( "Current jiffies is %lx/n", jiffies );
 
  n = 0;
  //n = syscall(__NR_wenxy_test);
  n = wenxy_test();
  printf("Wenxy: syscall return value is [%d], system call ID=[%d]/n", n, __NR_wenxy_test);
 
  return 0;
}
編譯test.c的命令:mipsel-linux-gcc -I/opt/bcm97405/kernel/stblinux-2.6.18 test.c


或者自己寫彙編程式:
用重新編譯後的核心啟動,如下程式測試之:

.text
.globl  main
.ent    main

main:

    li  $2, 4316    /* wenxy_test 的系統的呼叫號 */
    syscall

.end    main


其中 MIPS 下系統呼叫的約定為:

v0:         用於置系統呼叫號
a0~a3:      置前四個引數,後面的引數用棧傳
syscall      系統呼叫觸發指令


編譯 gcc cat.S -o a.out

執行 ./a.out

正確的話應有如下輸出:
# a.out
kernel, wenxy debug:    into [arch/mips/kernel/syscall.c], call [sys_wenxy_test()]
Wenxy: syscall return value is [100], system call ID=[4316]

PS.
a. 可以用dmesg檢視核心日誌,或者用strace a.out來跟蹤系統呼叫資訊。
b. 參考資料:
http://www.ibm.com/developerworks/cn/linux/l-system-calls/index.html
http://www.diybl.com/course/3_program/hb/hbjs/200798/70400.html#

相關文章