Arm Linux系统调用流程详细解析
时间:11-09
来源:互联网
点击:
所表明的那样,分别是函数的参数类型及参数名。__syscall_open实际上为:
int __syscall_open (const char * file,int flags, __kernel_mode_t mode){return (int) (INLINE_SYSCALL(__syscall_open, 3, file, flags, mode));}
INLINE_SYSCALL为同一个文件中定义的宏:
#undef INLINE_SYSCALL#define INLINE_SYSCALL(name, nr, args...) \({ unsigned int _inline_sys_result = INTERNAL_SYSCALL (name, , nr, args); \if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ), 0)) \{ \__set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, )); \_inline_sys_result = (unsigned int) -1; \} \(int) _inline_sys_result; })#undef INTERNAL_SYSCALL#if !defined(__thumb__)#if defined(__ARM_EABI__)#define INTERNAL_SYSCALL(name, err, nr, args...) \({unsigned int __sys_result; \{ \register int _a1 __asm__ ("r0"), _nr __asm__ ("r7"); \LOAD_ARGS_##nr (args) \_nr = SYS_ify(name); \__asm__ __volatile__ ("swi 0x0 @ syscall " #name \: "=r" (_a1) \: "r" (_nr) ASM_ARGS_##nr \: "memory"); \__sys_result = _a1; \} \(int) __sys_result; })#else /* defined(__ARM_EABI__) */#define INTERNAL_SYSCALL(name, err, nr, args...) \({ unsigned int __sys_result; \{ \register int _a1 __asm__ ("a1"); \LOAD_ARGS_##nr (args) \__asm__ __volatile__ ("swi %1 @ syscall " #name \: "=r" (_a1) \: "i" (SYS_ify(name)) ASM_ARGS_##nr \: "memory"); \__sys_result = _a1; \} \(int) __sys_result; })#endif#else /* !defined(__thumb__) *//* We cant use push/pop inside the asm because that breaksunwinding (ie. thread cancellation).*/#define INTERNAL_SYSCALL(name, err, nr, args...) \({ unsigned int __sys_result; \{ \int _sys_buf[2]; \register int _a1 __asm__ ("a1"); \register int *_v3 __asm__ ("v3") = _sys_buf; \*_v3 = (int) (SYS_ify(name)); \LOAD_ARGS_##nr (args) \__asm__ __volatile__ ("str r7, [v3, #4]\n" \"\tldr r7, [v3]\n" \"\tswi 0 @ syscall " #name "\n" \"\tldr r7, [v3, #4]" \: "=r" (_a1) \: "r" (_v3) ASM_ARGS_##nr \: "memory"); \__sys_result = _a1; \} \(int) __sys_result; })#endif /*!defined(__thumb__)*/
这里也将同文件中的LOAD_ARGS宏的定义贴出来:
#define LOAD_ARGS_0()#define ASM_ARGS_0#define LOAD_ARGS_1(a1) \_a1 = (int) (a1); \LOAD_ARGS_0 ()#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1)#define LOAD_ARGS_2(a1, a2) \register int _a2 __asm__ ("a2") = (int) (a2); \LOAD_ARGS_1 (a1)#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2)#define LOAD_ARGS_3(a1, a2, a3) \register int _a3 __asm__ ("a3") = (int) (a3); \LOAD_ARGS_2 (a1, a2)
这项宏用来在相应的寄存器中加载相应的参数。SYS_ify宏获得系统调用号
#define SYS_ify(syscall_name) (__NR_##syscall_name)
也就是__NR___syscall_open,在libc/sysdeps/linux/common/open.c中可以看到这个宏的定义:
#define __NR___syscall_open __NR_open
__NR_open在内核代码的头文件中有定义。在r7寄存器中存放系统调用号,而参数传递似乎和普通的函数调用的参数传递也没有什么区别。
在这个地方,得注意那个EABI,EABI是什么东西呢?ABI,Application Binary Interface,应用二进制接口。在较新的EABI规范中,是将系统调用号压入寄存器r7中,而在老的OABI中则是执行的swi中断号的方式,也就是说原来的调用方式(Old
ArmLinux系统调 相关文章:
- ARM Linux下添加新的系统调用(11-21)
- 《ARM与Linux些许问题》第四章:ARM平台系统调用原理分析(11-09)
- Arm linux 系统调用分析(11-09)
- Android arm linux 系统调用实现(11-09)
- arm linux 系统调用实现(11-09)
- Arm Linux系统调用流程详细解析SWI(11-09)