11

在 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’

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

4

2 回答 2

16

状态的联机帮助页_syscall(2)

从内核 2.6.18 开始,_syscall 宏已从提供给用户空间的头文件中删除。请改用 syscall(2)。(一些架构,尤其是 ia64,从未提供 _syscall 宏;在那些架构上,总是需要 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 架构的示例。

首先,您必须从表中获取系统调用号,例如这个表。在 的情况下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
于 2012-11-04T14:57:40.730 回答
-8

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

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

想找出当前进程的进程id

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

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

问候,祖布拉伊

于 2012-11-05T11:28:37.210 回答