您的位置:首页 > 运维架构 > Linux

MIPS Linux 下添加系统调用,以Linux kernel 2.6.18为例.

2009-11-20 14:37 746 查看
 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#
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息