如何使用我的自定义系统调用的名称而不是其编号

时间:2014-04-27 15:00:45

标签: c linux-kernel

可能我混淆了一些概念,但我遇到了这个问题:

要使用我的系统调用,请运行以下代码:

#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h> 

#define __NR_hello 337 

long hello_syscall(void) { 
  return syscall(__NR_hello); 
} 

int main(int argc, char *argv[]) { 

  long int a = hello_syscall(); 
  printf(“System call returned %ld\n”, a); 

  return 0;
}

通过这种方式,它的工作原理!但是,如果我想做下面的事情,只使用系统调用名称而没有数字的定义等,该怎么办?

#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>  

int main(int argc, char *argv[]) { 

  long int a = hello(); 
  printf(“System call returned %ld\n”, a); 

  return 0;
}

我是否必须包含自定义头文件?

2 个答案:

答案 0 :(得分:3)

所有系统调用都以您的方式调用。

唯一的区别是包装器(作为您为自己的系统调用提供的hello_syscall())是链接到您的程序的一些库的一部分,默认情况下使用libc很多。

为了能够简单地将hello()重命名为hello_syscallhello,请将其放在lib中,将此lib链接到您的程序。没有自动化为你做这件事。

你永远不会直接调用内核。

要了解如何为其他系统调用执行此操作,请查看您最喜欢的libc实现的来源。

更新

如果可能的话,将附加系统调用放入模块中。这使您不必首先修补内核以使系统调用可用。

答案 1 :(得分:0)

在大多数情况下,系统调用将通过处理软件中断来实现。这个触发的中断将控制一个系统调用处理程序,该处理程序将基于一个syscall-id决定必须调用哪个函数来处理该特定的中断。

以下是osdev.org的一个小例子(见example):

IntA9Handler:
    CMP AH, 1             ; Syscall Nr for read()
    JNE .write
    CALL _read            ; Call read()
    JMP .done
.write:
    CMP AH, 2             ; Syscall Nr. for write()
    JNE .badcode
    CALL _write           ; Call write
    JMP .done
.badcode:
    MOV EAX, 0FFFFFFFFh
.done:
    IRETD

基本上是这样的:

int syscall(int syscall_id)
{
  if ( syscall_id == SYSCALL_READ ) { 

    return read();
  } 
  else if ( syscall_id == SYSCALL_WRITE )

    return write();
  }

  return SYSCALL_ERROR;
}

所以你看,你总是必须在某个时刻向内核提供。