微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Arm Linux系统调用流程详细解析

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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top