据我所知,ARM ABI for ARM声明syscall返回值是通过r0
传递的,如果它是负数,则它应该被线程化为errno值否定。即系统调用最终出现了一些错误。
AOSP does this check以某种奇特的方式:
ENTRY(syscall)
mov ip, sp
stmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 16
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
mov r7, r0
mov r0, r1
mov r1, r2
mov r2, r3
ldmfd ip, {r3, r4, r5, r6}
swi #0
ldmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 0
cmn r0, #(MAX_ERRNO + 1) /* Set C flag if r0 is between -4095 and -1, set Z flag if r0 == -4096 */
bxls lr /* return if Z is set or C is clear */
neg r0, r0
b __set_errno_internal
END(syscall)
看起来这个函数不会成为威胁r0 < -4096
的错误条件。虽然它应该。当然,真正的errno
将适合允许的差距,但无论如何,以这种方式执行检查的理由是什么,而不是仅仅测试r0
的否定性?
P.S。如果我错过了某些内容或只是我的分析不正确 - 任何评论都会受到赞赏。
答案 0 :(得分:3)
如果解释为带符号的数字,*ngIf="item === 'somevalue'"
的返回值通常为负。
答案 1 :(得分:3)
这是Linux的系统调用ABI / API的设计方式,以避免在一小组错误代码中使用一半可能的返回值。 (没有人需要超过4095个errno代码?)
正如@Timothy指出的那样,mmap
是一个很好的例子:它需要返回一个指针。 mmap
的返回值始终是页面对齐的,因此对于具有4k页或更大页面的系统(即几乎(?)所有内容),-4095
是您可以使用的最高幅度负数,而不是有效的页面地址。
-4095
= 2^32 - 4095
。最高的网页起始地址为2^32-4096
。这是明确选择此范围的明显动机,即那些意味着“错误”的范围。
意味着错误的值的范围在理论上是平台依赖的并且是系统调用ABI的一部分,但AFAIK Linux在它支持的每个平台上使用[-4095..-1]
。 MUSL libc实现在C源文件中硬编码-4096UL
,该文件不是x86或特定于ARM的:/src/internal/syscall_ret.c
。正如@Tsyvarev指出的那样,Linux将MAX_ERRNO
定义为4095 in include/linux/err.h
,而不是特定于arch的标头。 (注释指出,如果需要它可以使它成为特定于arch的,并且由于内核指针的工作方式而特别选择它。)
x86-64 System V ABI确实有一个关于Linux系统调用的信息性(非规范性)部分,其中指定了-4095
到-1
范围。 (Search for -4095
)。
有趣的事实:sys_getpriority
无法直接返回nice
级别。而是it returns 20-nice
, which maps the -20..19
range of nice values to 40..1
。通用包装器可以使用retval > -4096UL
检查错误,因为所有系统调用都避免返回该范围内的非错误值,即使它们必须通过环形跳转来执行此操作。
相关:
答案 2 :(得分:2)
对于errno值的Apper限制4095是有意的,并且在代码中使用这些知识是可以的。实际上,这会修改值的模型,通过系统调用和其他一些内核函数返回到:
[-4095 ... -1]
- 错误此模型允许更多可能的结果值。例如,如果将结果解释为无符号长整数,则结果的值范围从[0... (MAX/2)]
扩展到[0 ... (MAX - 4096)]
。这很有用,例如当结果是指针时,请参阅IS_ERR
宏的implementation。