有人可以向我解释这段代码吗? 还请给我一些链接/ URL,我可以在这里了解更多信息? 此代码用作包装器来覆盖库中的“extern int errno”。有人可以解释我这个功能,并告诉为什么在一些系统调用中需要包装器?哪个也叫做WeakSYSCALLS?
#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1)
#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2)
#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3)
#define LOADREGS_5(a1, a2, a3, a4, a5) \
register int _v1 asm ("v1") = (int) (a5); \
LOADREGS_4 (a1, a2, a3, a4)
#define LOADREGS_6(a1, a2, a3, a4, a5, a6) \
register int _v2 asm ("v2") = (int) (a6); \
LOADREGS_5 (a1, a2, a3, a4, a5)
#define MYLIBC_SYSCALL(name, nargs, args...) \
({ \
unsigned int retval; \
{ \
register int _a1 asm ("r0"), _nargs asm ("r7"); \
LOADREGS_##nargs(args) \
_nargs = __NR_##name; \
asm volatile ( \
"swi 0x0" \
:"=r"(_a1) \
:"r"(_nargs) ASM_ARGS_##nargs \
: "memory" ); \
retval = _a1; \
} \
if ( retval >= 0xfffff001 ) { \
errno = -retval; \
retval = (unsigned int)-1; \
} \
(int) retval; \
})
答案 0 :(得分:5)
执行“系统调用”意味着触发内核执行特殊活动。由于内核在不同的地址空间中运行,因此无法通过简单的函数调用来完成。
根据操作系统和硬件平台的不同,可以通过触发中断,调用门,SYSENTER或其他几种方法来调用系统调用。
但是,在任何情况下,您都不能像使用C函数调用那样简单地将许多参数传递给内核。但是,可以将参数值放入某些寄存器中。哪些注册,以及内核如何解释它们的内容,再次特定于所讨论的操作系统。
由于您既不能访问特定的寄存器,也不能调用上面提到的任何内核触发方法,所以在普通的C代码中, syscall包装器可用于调用与C函数类似,然后将参数放在寄存器中并使用ASM代码触发内核。
您在上面看到的是这样一个系统调用包装器。您可以看到将参数数量放入寄存器r7的部分,参数本身放入适当的寄存器(LOADREGS_*
),然后执行触发器(swi 0x0
,我猜测是软件中断 - 我对ARM平台了解不多,并从寄存器A1获取“返回值”。
答案 1 :(得分:0)
系统调用无法直接设置errno
,而是返回负值。 errno
实际上应该是一个评估为左值的宏。
此代码更新您的errno副本而不是C库的副本。