【发布时间】:2015-06-16 13:52:52
【问题描述】:
我正在查看一些 Android 源代码,发现 writev 的实现完全是在汇编中。我对 ASM 有一般的工作知识,但不熟悉 ARM 指令集的细微差别。考虑到这段代码:
ENTRY(writev)
mov ip, r7
ldr r7, =__NR_writev
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
END(writev)
经过一番搜索,我发现了以下内容:
__NR_writev = __NR_SYSCALL_BASE+146
__NR_SYSCALL_BASE = 0
这里到底发生了什么?据我所知,ip 寄存器是 r12 的别名,也称为暂存寄存器。我可以在源代码中找到的几乎所有 ASM 实现都有这样的总体布局:
代码将r7加载到ip中,r7加载了例程的实际内存地址,然后发出软件中断。虽然我不知道到底发生了什么,但我可以看到剩余的代码正在使用 __NR_writev 子例程调用的返回值检查错误。
如果此 ASM 例程仅重定向调用并检查错误,那么 writev 的 实际 实现在哪里?
为什么将 r7 保存在这里以及为什么保存到 ip(r12/scratch register) 中?
为什么实际实现的内存地址在 SWI 之前加载到 r7 中?
【问题讨论】:
-
“实际实现在哪里......” - 你知道what a syscall is,对吧? ;)
-
@Notlikethat,当然。也许不是。你什么意思?我知道用户空间中的用户 do 的系统调用是什么,但它们的实现是我不熟悉的。
-
@sherrellbc 实现将在操作系统源代码中。
-
这类似于函数调用,但它是系统调用,有一个系统处理程序正在执行实际工作,这只是传递参数和进行系统调用的包装器,操作系统正在工作
-
@sherrellbc 系统调用号是系统调用表中的条目。 writev 可通过 sycall 表中的第 146 个函数指针访问。这些数字是固定的,因为当发布新版本的内核时,还需要新版本的 libc(带有更新的系统调用编号)