linux系统调用编写方法变化

2.6的时代,写一个linux的系统调用的步骤是这样的:

  1. 编写实际操作函数
  2. 在linux/include/asm-i386/unistd.h中添加宏定义
    #define __NR_myfunctioin 399
    
  3. 在linux/arch/i386/kernel/entry.S中添加
    .long SYMBOL_NAME(myfunction)
    
  4. 通过_syscall[1-6](type, name, type, arg1)来调用

最新版本的kernel对应位置找不到相应的宏定义文件了
unistd.h文件修改为分别对32和64位的版本的引用,并分别放置在了/arch/x86/include/uapi/asm/unistd[32|64|x32].h,`arch/x86[_64]/syscalls/syscall[32|64].tbl, arm的放置在了/arch/arm/include/uapi/asm/unistd.h中,其它架构的位置有所不同entry.S文件也中sys_call_table的相关定义也放置在了syscall.h文件中,将原来的汇编并修改为C数组的定义方式。x86下syscalltbl.sh`会根据tbl的定义动态生成。
tbl的定义格式为:

<number> <abi> <name> <entry point> <compat entry point>
1 i386 exit sys_exit
2 i386 fork sys_fork stub32_fork

在include/linux/syscalls.h添加原型:


asmlinkage long sys_exit(int error_code); asmlinkage long sys_fork(void);

asmlinkage的原型是:


#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))

另外有些文件修改为了SYSCALL(n, call)方式定义,SYSCALL是宏

#define __SYSCALL(n, call) [nr] = (call),#define __SYSCALL_XX(n, sym, compat)

另外x86的在arch/x86/kernel/syscall_[32|64].c添加了sys_call_table[__NR_syscalls_max+1]数组

typedef asmlinkage void (*sys_call_ptr_t)(void);
extern asmlinkage void sys_ni_syscall(void);
void sys_call_ptr_t sys_call_table[__NR_syscalls_max+1] = {
         [0 ... __NR_syscalls_max] = &sys_ni_syscall,
        #include <asm/syscalls_[32|64].h>
}

arm64的在arch/arm/kernel/sys.c

void *sys_call_table[__NR_syscalls] __aligned(4096) = {
    [0 ... __NR_syscalls - 1] = sys_ni_syscall,
#include <asm/unistd.h>
};

arm的在arch/arm/kernel/entry-common.S

ENTRY(sys_call_table)
#include "calls.S"
#undef ABI
#undef OBSOLETE

对应的callss.S内容为

CALL(sys_restart_syscall)
CALL(sys_exit)
....

目前,kernel中存在直接使用宏定义数字和__SYSCALL两种方式方式来定义系统调用的。

你可能感兴趣的:(linux,kernel,内核)