【问题标题】:Details of Syscall.RawSyscall() & Syscall.Syscall() in Go?Go 中 Syscall.RawSyscall() 和 Syscall.Syscall() 的详细信息?
【发布时间】:2024-10-24 01:55:02
【问题描述】:

我现在正在阅读包syscall中的源代码,遇到了一些问题:

由于我完全是 syscallassembly 的菜鸟,所以请不要犹豫,分享你所知道的任何事情:)

首先关于funcRawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno):它的参数trap, a1, a2, a3&返回值r1 r2是什么意思?我搜索了文档和网站,但似乎没有关于此的描述。

其次,由于我使用的是darwin/amd64,所以我搜索了源代码并在这里找到了它: http://golang.org/src/pkg/syscall/asm_darwin_amd64.s?h=RawSyscall

好像是assemble写的(看不懂),能不能解释一下第61-80行发生了什么,第76行下ok1:部分是什么意思?

我还在http://golang.org/src/pkg/syscall/zsyscall_darwin_amd64.go 中找到了一些代码,zsyscall 的文件名是什么意思?

syscallrawsyscall 有什么区别?

如果我想编写自己的系统调用函数,如何以及何时使用它们(是的,os 包提供了很多选择,但仍有一些情况它没有涵盖)?

这么多菜鸟问题,感谢您的耐心阅读和回答:)

【问题讨论】:

    标签: unix assembly operating-system go system-calls


    【解决方案1】:

    我将与您分享我减少的组装知识:

    61  TEXT ·RawSyscall(SB),7,$0
    62      MOVQ    16(SP), DI
    63      MOVQ    24(SP), SI
    64      MOVQ    32(SP), DX
    65      MOVQ    $0, R10
    66      MOVQ    $0, R8
    67      MOVQ    $0, R9
    68      MOVQ    8(SP), AX   // syscall entry
    69      ADDQ    $0x2000000, AX
    70      SYSCALL
    71      JCC ok1
    72      MOVQ    $-1, 40(SP) // r1
    73      MOVQ    $0, 48(SP)  // r2
    74      MOVQ    AX, 56(SP)  // errno
    75      RET
    76  ok1:
    77      MOVQ    AX, 40(SP)  // r1
    78      MOVQ    DX, 48(SP)  // r2
    79      MOVQ    $0, 56(SP)  // errno
    80      RET
    81  
    
    • 第 61 行是例程入口点
    • 第 76 行是一个名为 ok1 的标签
    • 第 71 行是到标签 ok1 的条件跳转。

    您在左侧每一行看到的短名称称为mnemonics,代表汇编指令:

    • MOVQ 表示移动四字(64 位数据)。
    • ADDQ 是添加四字。
    • SYSCALL 有点明显
    • JCC是Jump if Condition(前一条指令设置的条件标志)
    • RET 是返回

    在助记符的右侧,您会发现每条指令的参数基本上是常量和registers

    • SP 是堆栈指针
    • AX 是累加器
    • BX 是基址寄存器

    每个寄存器可以保存一定数量的数据。在 64 位 CPU 架构上,我相信它实际上是每个寄存器 64 位。

    SyscallRawSyscall 之间的唯一区别在于第 14、28 和 34 行,其中Syscall 将调用runtime·entersyscall(SB)runtime·exitsyscall(SB),而RawSyscall 不会。我假设这意味着 Syscall 通知运行时它已切换到阻塞系统调用操作,并且可以将 CPU 时间分配给另一个 goroutine/线程,而 RawSyscall 只会阻塞。

    【讨论】:

    • 感谢您的快速回复,这是否意味着程序员应该在非阻塞情况下使用Syscall,在阻塞情况下使用RawSyscall
    • 我认为用户级代码应始终使用Syscall,而RawSyscall 存在于非常特定的情况。
    • RawSyscall 用于调用您知道不会阻塞的系统调用,但开销略小(因为不调用运行时函数)。
    最近更新 更多