我认为你可能会感到困惑的是,syscall
它不执行任何一项操作。而是,它是通用API,可用于你可能要求内核执行的任何操作-打开文件,映射内存,派生新进程等。
你希望内核执行的特定操作是使用syscall号选择的。只需从表中选择第一个,系统调用0(称为sys_read
)就会从文件中读取。
显然,由不同的系统调用执行的操作需要不同的参数。与该sys_read
示例相同,我们在表中看到它带有三个参数:文件描述符(fd
),指向缓冲区的指针(buf
)和要读取的字节数(count
)。因此,如果你要调用此syscall,则可以按以下步骤进行操作:
#include <sys/syscall.h>
// Assuming these have been initialized appropriately.
unsigned int fd = ...;
char * buf = ...;
size_t count = ...;
syscall(SYS_read, fd, buf, count);
该答案提供了有关何时可能要选择使用的更多信息syscall
。简短的版本是使用的原因syscall
很少。
编辑:正如@PeterCordes所指出的,ABI之间的系统调用号有所不同,因此你应该使用中定义的常量,sys/syscall.h
而不要自己对系统调用号进行硬编码。
您在上一段中链接的答案描述了何时要
syscall(int, ...)
在C中使用包装函数。不是在asm中内联syscall的syscall
指令。如果您正在玩玩具程序并且没有链接libc,则通常希望直接使用syscall。@PeterCordes:有
syscall
指示吗?在较早的时候,我们使用了INT
,后来又使用了,ENTER
现在我认为只有一个JMP
(没有实际地址,“段”的选择器表具有要执行哪个环和哪个内核地址的数据)@GiacomoCatenazzi:是的,AMD推出了
syscall
,并对其进行了重新设计以用于AMD64。这是在Linux上从用户空间使用64位系统调用ABI的唯一方法。enter
可用于系统调用是不合理的–这是制作堆栈帧的缓慢方法;也许您在考虑sysenter
(英特尔的32位快速系统调用指令)?请参阅如果以64位代码使用32位int 0x80 Linux ABI会发生什么?两者之间的差异以及使用Linux的示例write
。@MartinB:哦,您是对的,这是带有标签的,
[x86-64]
但没有[assembly]
,并且syscall(2)
在标题中。我们对syscall
指令有很多疑问,OP的第一个链接是汇编语言。在我遵循的标签中,我基本上从未见过这样的标签,而且我浏览过快,以至于我发现自己做出了错误的假设>。<由于您给出的是一个可移植的答案,因此您不想对电话号码进行硬编码-ISA之间甚至i386和amd64之间它们都不同。在包含适当的标题(或)后使用
__NR_read
或。 在x86-64上为0,但在i386上不是0。SYS_read
<asm/unistd.h>
<sys/syscall.h>
__NR_read