c++ - 如何在不使用程序集的情况下以独立于 cpu 的方式从 C/C++ 应用程序进行 Linux 系统调用?

标签 c++ c linux assembly system-calls

<分区>

我希望编写一个需要对进程进行低级别工作的程序(即使用 fork 系统调用等)。该程序将用 C++ 编写,并且只能在 Linux 上运行。理想情况下,它可以跨 CPU 架构(即 x86、x86_64 和 arm)移植,只需重新编译即可,但我只真的需要 x86_64 支持。

由于每个 Linux 系统调用都接受多个参数并在 cpu 寄存器中返回多个参数(通常只有 1 个返回值),因此很容易为每个系统调用创建一个 C 函数包装器。另外,据我所知,在内核中实现的系统调用具有相同的参数和返回值,如果不同的汇编级实现,则可以公开相同的 C 接口(interface)。

有这样的东西吗?如果是这样,我该如何访问它?

它的文档在哪里(可用函数的列表、它们的参数及其解释,以及函数的确切作用的解释)?

最佳答案

libc 已经包含了您正在寻找的包装函数。其中许多的原型(prototype)在 #include <unistd.h> 中。 ,由 POSIX 指定。

C 是 Unix(和 Linux)上的低级系统程序语言,所以自 Unix 存在以来这就是一回事。 (在 libc 中提供包装函数比教编译器函数调用和系统调用之间的区别更容易,并且允许在错误时设置 errno。它还允许像 LD_PRELOAD 这样的技巧来拦截用户空间中的系统调用。)


系统调用的手册页在第 2 节,而库函数的第 3 节(可能会或可能不会使用系统调用作为其实现的一部分:math.h cos(3)、ISO C stdio printf(3)fwrite(3) ,与 POSIX write(2) 相比)。

execve(2) 是系统调用。

参见 execl(3) 和 friend 也是libc的一部分,最终调用execve(2) .它们是构建 argv 数组的便利包装器,做 $PATH查找,并传递当前进程的环境。因此它们被归类为函数,而不是系统调用。

参见 syscalls(2) 获取系统 Linux 调用的概述和完整列表,以及指向其手册页包装器的链接。 (我已经链接了 Linux 手册页,但也有所有标准系统调用的 POSIX 手册页。)


在极少数情况下您没有链接 libc,您可以使用像 MUSL 的 syscall2 这样的宏。/syscall3/等宏(数字是 arg 计数)在任何平台上内联正确的 asm。您使用 __NR_write来自 asm/unistd.h获取系统调用号。

但请注意,原始 Linux 系统调用可能与 libc 包装器提供的接口(interface)有细微差别。例如,他们不会检查 pthreads 取消点,和 brk/sbrk需要 libc 在用户空间中进行簿记。

参见 SYSCALL_INLINE in Android用于可移植原始 sys_write()使用 MUSL 宏的内联包装器。

但是如果你像普通人一样使用 libc 来实现类似 malloc 的功能和 printf ,您应该只使用它的系统调用包装函数。

关于c++ - 如何在不使用程序集的情况下以独立于 cpu 的方式从 C/C++ 应用程序进行 Linux 系统调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51120807/

相关文章:

c++ - 为什么初始化列表中的元素数量会导致模棱两可的调用错误?

c++ - 我什么时候会在 constexpr 上使用 std::integral_constant?

linux - shell脚本 "expect"ing来自ssh的各种响应

c++ - 将文件读入 STL vector 时删除\r\n

c++ - 使用类成员函数作为比较器调用 std::equal 时出错

计算文件中的字符我找不到问题

C 字符串数组输出不正确

c - 使用 EXTERN 使用混合代码的引导加载程序

linux - 尝试使用 Spring Tools Suite 导入时端口超出范围 -1

linux - Linux RSS 不等于 java Xx + MaxMetaspaceSize 吗?