直接从用户程序访问系统调用
在Ubuntu上 – 内核2.6.32.2
如何在没有任何库帮助的情况下直接从用户代码调用已有的系统调用? 我读书和在互联网上解决这个问题,然后写下面的代码但仍然出错。 请帮忙
想要找出当前进程的进程ID
#include #include // for __NR_getpid _syscall0(int, getpid) int main() { printf("Current Process ID : %d\n",getpid()); return 0; }
编译时出错:
root@Omkant:~/os# gcc -Wall getpid.c -o getpid getpid.c:5:16: error: expected declaration specifiers or '...' before 'getpid' getpid.c:5:1: warning: data definition has no type or storage class getpid.c:5:1: warning: type defaults to 'int' in declaration of '_syscall0' getpid.c: In function 'main': getpid.c:8:2: warning: implicit declaration of function 'getpid'
代码中的问题是什么? 请帮忙…
_syscall(2)
的联机帮助页指出:
从内核2.6.18开始,从提供给用户空间的头文件中删除了_syscall宏。 请改用syscall(2)。 (有些架构,尤其是ia64,从未提供_syscall宏;在这些架构上,总是需要syscall(2)。)
因此,您所需的方法无法在更现代的内核上运行。 (您可以清楚地看到,如果您在代码上运行预处理器。它将无法解析_syscall0
宏)尝试使用syscall
函数:
以下是syscall(2)
引用的示例:
#define _GNU_SOURCE #include #include #include int main(int argc, char *argv[]) { pid_t tid; tid = syscall(SYS_gettid); }
当您要求直接调用Linux内核而没有任何用户空间包装器时,我将向您展示80386和amd64架构的示例。
首先,您必须从表中获取系统调用号,例如此表。 在getpid
情况下,amd64的系统调用号为getpid
的系统调用号为20.接下来,我们创建一个为我们调用系统的函数。 在80386处理器上,您使用中断128来调用系统,在amd64上我们使用特殊的syscall
指令。 系统调用号进入寄存器eax,输出也写入该寄存器。 为了使程序更容易,我们在汇编中编写它。 您可以稍后使用stracevalidation它是否正常工作。
这是80386的代码。它应该返回其pid的最低字节作为退出状态。
.global _start _start: mov $20,%eax #system call number 20: int $128 #call the system mov %eax,%ebx #move pid into register ebx mov $1,%eax #system call number 1: exit, argument in ebx int $128 #exit
组装:
as -m32 -o 80386.o 80386.s ld -m elf_i386 -o 80386 80386.o
这是amd64的相同代码:
.global _start _start: mov $39,%eax #system call 39: getpid syscall #call the system mov %eax,%edi #move pid into register edi mov $60,%eax #system call 60: exit syscall #call the system
组装:
as -o amd64.o amd64.s ld -o amd64 amd64.o
“如何在没有任何图书馆帮助的情况下直接从用户代码调用已经存在的系统调用?我在书籍和互联网上阅读以解决这个问题,然后编写下面的代码但仍然出现错误”
你的问题就像询问如何使用printf而不使用glibc / libc一样,我想只有一个解决方案获取printf的源代码,将其粘贴到你的代码中并使用它
想要找出当前进程的进程ID
可以通过使用libc中的getpid函数找到进程id,它负责你的系统调用。
系统调用未在库中定义,这些是为访问内核数据而编写的函数。
问候,Zubraj