可能我混淆了一些概念,但我遇到了这个问题:
要使用我的系统调用,请运行以下代码:
#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;
}
我是否必须包含自定义头文件?
答案 0 :(得分:3)
所有系统调用都以您的方式调用。
唯一的区别是包装器(作为您为自己的系统调用提供的hello_syscall()
)是链接到您的程序的一些库的一部分,默认情况下使用libc很多。
为了能够简单地将hello()
重命名为hello_syscall
到hello
,请将其放在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;
}
所以你看,你总是必须在某个时刻向内核提供。