直接从用户程序访问系统调用

时间:2012-11-04 14:42:25

标签: c posix system-calls

在Ubuntu上 - 内核2.6.32.2

如何在没有任何图书馆帮助的情况下直接从用户代码调用已有的系统调用? 我读书和在互联网上解决这个问题,然后写下面的代码但仍然出错。请帮忙

想要找出当前流程的流程ID

#include <stdio.h>
#include<linux/unistd.h> // 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’

代码中的问题是什么?请帮忙......

2 个答案:

答案 0 :(得分:12)

_syscall(2)州的联合帮助页:

  

从内核2.6.18开始,从提供给用户空间的头文件中删除了_syscall宏。请改用syscall(2)。 (有些架构,尤其是ia64,从未提供_syscall宏;在这些架构上,始终需要系统调用(2)。)

因此,您所需的方法无法在更现代的内核上运行。 (您可以清楚地看到,如果您在代码上运行预处理器。它将无法解析_syscall0宏)请尝试使用syscall函数:

以下是syscall(2)引用的使用示例:

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>

int
main(int argc, char *argv[])
{
    pid_t tid;
    tid = syscall(SYS_gettid);
}

当您要求直接调用Linux内核而没有任何用户空间包装时,我将向您展示80386和amd64架构的示例。

首先,您必须从表中获取系统调用号,例如this one。在getpid的情况下,amd64的系统调用号为39,80386的系统调用号为20.接下来,我们创建一个为我们调用系统的函数。在80386处理器上,您使用中断128来调用系统,在amd64上我们使用特殊的syscall指令。系统调用号进入寄存器eax,输出也写入该寄存器。为了使程序更容易,我们在汇编中编写它。您可以稍后使用strace来验证它是否正常工作。

这是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

答案 1 :(得分:-6)

“如何在没有任何图书馆帮助的情况下直接从用户代码调用已经存在的系统调用?我在书籍和互联网上阅读以解决这个问题,然后写下面的代码,但仍然出现错误”

你的问题就像询问如何在不使用glibc / libc的情况下使用printf一样,我想只有一个解决方案获取printf的源代码,将其粘贴到你的代码中并使用它

想要找出当前流程的流程ID

进程ID可以通过使用libc中的getpid函数找到,它负责你的系统调用。

系统调用未在库中定义,这些是为访问内核数据而编写的函数。

的问候, 祖布拉