0

0

Go 系统调用详解:RawSyscall 与 Syscall 的区别及使用

霞舞

霞舞

发布时间:2025-10-16 11:15:36

|

161人浏览过

|

来源于php中文网

原创

go 系统调用详解:rawsyscall 与 syscall 的区别及使用

本文旨在深入解析 Go 语言 `syscall` 包中的 `RawSyscall` 和 `Syscall` 函数。我们将详细解释 `RawSyscall` 的参数和返回值,解读其汇编实现的关键部分,并阐明 `Syscall` 与 `RawSyscall` 的本质区别。此外,本文还将指导开发者在需要自定义系统调用时,如何选择和使用这两个函数。

RawSyscall 函数详解

RawSyscall 函数是 Go 语言中直接进行系统调用的底层接口。其函数签名如下:

func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
  • trap: 系统调用号。每个操作系统都定义了一组系统调用,每个调用都有一个唯一的编号。trap 参数指定了要执行的系统调用的编号。
  • a1, a2, a3: 系统调用的参数。大多数系统调用都需要一些输入参数。a1、a2 和 a3 分别代表系统调用的前三个参数。如果系统调用需要的参数超过三个,则需要通过其他方式传递(例如,通过指针传递结构体)。
  • r1, r2: 系统调用的返回值。系统调用执行完成后,通常会返回一些结果。r1 和 r2 分别代表系统调用的前两个返回值。
  • err: 错误码。如果系统调用执行失败,则 err 返回一个 Errno 类型的值,表示错误码。

汇编代码解读 (以 darwin/amd64 为例)

以下是 RawSyscall 在 darwin/amd64 架构下的汇编代码片段:

TEXT ·RawSyscall(SB),7,$0
    MOVQ    16(SP), DI
    MOVQ    24(SP), SI
    MOVQ    32(SP), DX
    MOVQ    $0, R10
    MOVQ    $0, R8
    MOVQ    $0, R9
    MOVQ    8(SP), AX   // syscall entry
    ADDQ    $0x2000000, AX
    SYSCALL
    JCC ok1
    MOVQ    $-1, 40(SP) // r1
    MOVQ    $0, 48(SP)  // r2
    MOVQ    AX, 56(SP)  // errno
    RET
ok1:
    MOVQ    AX, 40(SP)  // r1
    MOVQ    DX, 48(SP)  // r2
    MOVQ    $0, 56(SP)  // errno
    RET
  • TEXT ·RawSyscall(SB),7,$0: 定义了 RawSyscall 函数的入口点。
  • MOVQ 16(SP), DI 等: 将参数从 (SP) 中移动到对应的寄存器中。DI, SI, DX 是通用寄存器,用于传递系统调用的参数。
  • MOVQ 8(SP), AX: 将系统调用号从栈中移动到 AX 寄存器。AX 寄存器用于指定系统调用号。
  • ADDQ $0x2000000, AX: 在 macOS 上,系统调用号需要加上 0x2000000 的偏移量。
  • SYSCALL: 执行系统调用指令。
  • JCC ok1: 如果系统调用成功,则跳转到 ok1 标签。JCC (Jump if Carry Clear) 是一个条件跳转指令,它会根据 CPU 的标志位来决定是否跳转。
  • MOVQ AX, 40(SP) 等: 将返回值从寄存器移动到栈中,以便 Go 代码可以访问它们。
  • RET: 从函数返回。

ok1: 标签

ok1: 标签是一个代码标签,用于标记代码中的一个位置。在上面的汇编代码中,JCC ok1 指令会根据系统调用的执行结果跳转到 ok1 标签。如果系统调用成功,则跳转到 ok1 标签,并将返回值存储到栈中。如果系统调用失败,则不跳转到 ok1 标签,而是执行后面的代码,将错误码存储到栈中。

Syscall 与 RawSyscall 的区别

Syscall 和 RawSyscall 的主要区别在于 Syscall 会调用 runtime·entersyscall(SB) 和 runtime·exitsyscall(SB),而 RawSyscall 不会。

  • runtime·entersyscall(SB): 通知 Go 运行时系统,当前 Goroutine 即将进入一个阻塞的系统调用。这允许 Go 运行时系统将 CPU 时间片让给其他 Goroutine,从而提高程序的并发性。
  • runtime·exitsyscall(SB): 通知 Go 运行时系统,当前 Goroutine 已经从系统调用返回。

因此,Syscall 适用于那些可能阻塞的系统调用,而 RawSyscall 适用于那些不会阻塞的系统调用或者对性能要求非常高的场景。

何时使用 Syscall 和 RawSyscall

独响
独响

一个轻笔记+角色扮演的app

下载
  • Syscall: 当你需要执行一个可能阻塞的系统调用时,例如文件 I/O、网络 I/O 等。
  • RawSyscall: 当你需要执行一个不会阻塞的系统调用,或者对性能要求非常高,并且你确信该系统调用不会阻塞时。例如,一些底层的硬件操作。

zsyscall 的含义

在 syscall 包中,以 zsyscall 开头的文件名通常表示该文件是自动生成的,用于提供特定操作系统和架构的系统调用实现。这些文件通常由 go tool cgo 工具根据 C 头文件自动生成。

编写自定义系统调用函数

如果你需要使用 Go 语言调用一些操作系统提供的,但 syscall 包没有封装的系统调用,你可以使用 RawSyscall 或 Syscall 函数。

示例

以下是一个使用 RawSyscall 调用 getpid 系统调用的示例:

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

func Getpid() (pid int) {
    pid, _, _ = syscall.RawSyscall(syscall.SYS_GETPID, 0, 0, 0)
    return
}

func main() {
    pid := Getpid()
    fmt.Println("Process ID:", pid)
}

注意事项

  • 在编写自定义系统调用函数时,需要仔细查阅操作系统的文档,了解系统调用的参数和返回值。
  • 需要注意不同操作系统和架构的系统调用号可能不同。
  • 使用 RawSyscall 时,需要确保系统调用不会阻塞,否则可能会导致整个程序hang住。建议优先使用 Syscall。
  • 系统调用属于底层操作,务必谨慎使用,避免出现安全漏洞或程序崩溃。

总结

RawSyscall 和 Syscall 是 Go 语言中进行系统调用的两个底层接口。Syscall 会通知 Go 运行时系统,当前 Goroutine 即将进入一个阻塞的系统调用,而 RawSyscall 不会。因此,Syscall 适用于那些可能阻塞的系统调用,而 RawSyscall 适用于那些不会阻塞的系统调用或者对性能要求非常高的场景。 在编写自定义系统调用函数时,需要仔细查阅操作系统的文档,了解系统调用的参数和返回值,并谨慎使用。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

773

2023.08.22

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

220

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

190

2025.07.04

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1072

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

148

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1144

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

13

2026.01.19

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

395

2023.07.18

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

26

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4.2万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号