在2.6的时代,写一个linux的系统调用的步骤是这样的:
- 编写实际操作函数
- 在linux/include/asm-i386/unistd.h中添加宏定义
#define __NR_myfunctioin 399 - 在linux/arch/i386/kernel/entry.S中添加
.long SYMBOL_NAME(myfunction) - 编译内核
- 通过_syscall[1-6](type, name, type, arg1)来调用
而最新版本的kernel对应位置找不到相应的宏定义文件了
unistd.h文件修改为分别对32和64位的版本的引用,并分别放置在了/arch/x86/include/uapi/asm/unistd_[32|64|x32].h,arm的放置在了/arch/arm/uapi/asm/unistd.h中,其它架构的也差不多的位置
另外有些文件修改为了__SYSCALL(n, call)方式定义
entry.S文件也中sys_call_table的相关定义也放置在了syscall.h文件中,将原来的汇编并修改为C数组的定义方式
__SYSCALL是宏
#define __SYSCALL(n, call) [nr] = (call),
#define __SYSCALL_XX(n, sym, compat)另外添加了sys_call_table[NR_syscalls]数组
void *sys_call_table[NR_syscalls] = {
[0 ... NR_syscalls-1] = sys_ni_syscall,
#include <asm/unistd.h>
}
目前,kernel中存在直接使用宏定义数字和__SYSCALL两种方式方式来定义系统调用的。
本文介绍了在不同版本的Linux内核中实现系统调用的方法变化,包括宏定义、头文件位置调整及C语言数组替代汇编等技术细节。

被折叠的 条评论
为什么被折叠?



