我正在学习操作系统课程,第一个任务是向内核添加一些系统调用(Redhat,内核版本 2.4)。
我已经添加了我认为需要添加的所有内容,但它仍然不起作用。
我正在尝试运行测试,我注意到包装器(我在下面添加了一个示例以及它的 sys_call 代码)没有链接系统调用。我知道这一点,因为我在系统调用中放置了一个 printk 并且它们从未出现(并且测试本身并没有给出我期望的结果)。
现在据我了解添加系统调用的开发过程是:
- 创建一个包装器,如说明中的示例包装器函数(我们称之为服务)。
- 将 sys_aservice 写入 .c 文件中,该文件将转到 linux-2.4.18-14custom 文件夹中的众多文件之一。它转到的文件取决于我要添加的服务类型(例如,如果它是文件系统服务,我会将它放在 fs 中)。
- 在表中添加系统调用的条目
/usr/src/linuxlinux-2.4.18-14custom/arch/i386/kernel/ entry.S
这是我一开始所做的,但似乎还不够(因为它似乎不起作用)。
我在网上查了一下(并阅读:如何添加系统调用),我读到我需要添加/更改以下内容才能使链接正常工作。
在 unistd.h 中为系统调用添加一行。它看起来像
定义 __NR_aservice
将服务添加到生成文件。因此,例如,如果我将 aservice.c 放在 fs 文件夹中,我会将 aservice.c 添加到 fs 中的 makefile 中。
创建一个 aservice.h 文件,该文件将转到 linux-2.4.18-14custom/include/linux (显然所有 h 文件都在哪里?)。这个 .h 文件将包含一个叫做“存根”的东西,它是从 unistd.h 中的宏自动生成的(.h 文件必须包含它),以便用户程序可以使用您的系统调用。存根的声明如下所示: _syscallN(return type, function name, arg1 type, arg1 name ...)" 其中“N”是参数的数量。
在 aservice.c 中的每个 sys_X 函数前添加关键字“asmlinkage”(需要包含 links.h)。所以函数声明看起来像: asmlinkage int sys_aservice(...){..} 然后将 .h 文件包含在 .c 文件中。
这一切都正确吗?因为即使在执行以下操作之后,似乎仍然没有调用系统调用。
这是一个示例包装器和系统调用实现:
int stop_monitor(int pid){
long __res;
__asm__ volatile (
"movl $244, %%eax;" << 244 is the entry in the sys_call table in entry.S
"movl %1, %%ebx;"
"int $0x80;"
"movl %%eax, %0"
: "=m" (__res)
: "m" (pid)
: "%eax", "%ebx"
);
if((unsigned long)(__res) >= (unsigned long)(-125)) {
errno = -(__res);
__res = -1;
}
return (int)(__res);
}
asmlinkage int sys_stop_monitor(int pid){
task_t* task = find_task_by_pid(pid);
if(!task)
return -ESRCH;
if(task->flagMonitor == 0)
return -EPERM;
task->flagMonitor = 0;
return 0;
}
我错过了什么?