在OpenBSD等Unix平台上如何直接调用syscall而不使用封装函数?
OpenBSD 直接执行系统调用的实现方案
1. 直接使用 libc 提供的 syscall() 函数
这是最符合你需求的实现方式,OpenBSD 的标准 C 库原生提供了通用系统调用入口函数,你想要的 syscall(4, 1, "hello!", 6) 形式代码可以直接运行。
使用步骤:
- 引入头文件
<sys/syscall.h>,这个头文件同时定义了所有系统调用的编号宏(比如SYS_write对应值就是4) - 直接按
syscall(系统调用号, 参数1, 参数2, ...)格式编写代码即可
可运行示例代码:
#include <sys/syscall.h> #include <unistd.h> int main(void) { // 两种写法都可以,直接写4和用SYS_write宏效果一致 // syscall(SYS_write, 1, "hello!", 6); syscall(4, 1, "hello!", 6); return 0; }
编译运行方式:
cc -o syscall_demo syscall_demo.c ./syscall_demo
运行后会直接在标准输出打印hello!。
2. 纯汇编实现无依赖系统调用
如果你连 libc 提供的syscall()封装都不想用,可以直接通过汇编指令触发系统调用,完全不依赖任何库函数。
以 amd64 架构 OpenBSD 为例,系统调用触发规则:
- 系统调用编号存入
rax寄存器 - 参数按顺序存入
rdi、rsi、rdx、r10、r8、r9寄存器 - 执行
syscall指令触发,调用返回值存在rax寄存器
对应write调用的汇编示例片段:
mov rax, 4 ; write系统调用编号为4 mov rdi, 1 ; 第一个参数:标准输出文件描述符1 mov rsi, msg_ptr ; 第二个参数:字符串首地址 mov rdx, 6 ; 第三个参数:字符串长度 syscall
注意:硬编码系统调用编号的代码不具备跨版本、跨架构兼容性,OpenBSD 不同版本间系统调用编号可能发生调整,非特殊需求不建议在生产代码中使用这类写法。
内容的提问来源于stack exchange,提问作者Dragos Polifronie
相关产品推荐
相关产品推荐

