3

我正在尝试编写自己的系统调用。它只会返回当前时间。我知道我应该做什么的概念,并且我确实通过了如下几个链接:

但我仍然很困惑,没有得到想要的结果。内核未编译并且由于问题而崩溃。我已经在 debian 最新的稳定版 3.XX 上试过了

有人可以向我指出一种干净hello world的程序来开发系统调用吗?

编辑

对于以下答案,这是我的问题:

  1. File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S在我的 linux 文件夹中找不到。我不得不即兴创作,因此修改了以下文件:linux-x.x.x/arch/x86/syscalls/syscall_64.tbl

  2. 上面提到的(1)新文件有不同的模式,<number> <64/x32/common> <name> <entry point>我的条目是`313 common

  3. 内核映像确实编译成功,但我无法调用该函数。undefined reference" error当我用 gcc 编译它时它给出了一个。为什么?

4

2 回答 2

7

这只是示例如何编写简单的内核系统调用。考虑以下 C 函数 system_strcpy(),它只是将一个字符串复制到另一个字符串:类似于 strcpy() 所做的。

#include<stdio.h>

long system_strcpy(char* dest, const char* src)
{
   int i=0;
   while(src[i]!=0)
      dest[i]=src[i++];

   dest[i]=0;
   return i;
}

写之前先得到一个内核源码tar,解压得到一个linux-xxx目录。

文件 1:linux-xxx/test/system_strcpy.c 在 linux-xxx 中创建一个目录,命名test并将这段代码保存为文件system_strcpy.c

#include<linux/linkage.h>
#include<linux/kernel.h>
asmlinkage long system_strcpy(char*dest, const char* src)
{
   int i=0;
   while(src[i]!=0)
      dest[i]=src[i++];

   dest[i]=0;
   return i;
}

文件 2:linux-xxx/test/Makefile在上面 创建Makefile的同一test目录中创建一个,并将这一行放入其中:

obj-y := system_strcpy.o

文件 3:linux-xxx/arch/x86/kernel/syscall_table_32.S 现在,您必须将系统调用添加到系统调用表中。将以下行追加到文件中:

.long system_strcpy

注意:对于内核 3.3 和更高版本。

*参考:linux-3.3.xx/arch/x86/syscalls/syscall_64.tbl*

在那里,现在在以下一系列行的末尾添加:

310 64 process_vm_readv sys_process_vm_readv

311 64 进程_vm_writev sys_process_vm_writev

312 64 kcmp sys_kcmp

313 64 系统_strcpy 系统_strcpy

3.3 版本的格式为: number abi name entry point

文件4:linux-xxx/arch/x86/include/asm/unistd_32.h

注意:本节对于 3.3 和更高版本的内核是多余的

在此文件中,所有系统调用的名称将与一个唯一编号相关联。在最后一个系统呼叫号码对之后,添加一行

#define __NR_system_strcpy 338

(如果 337 是与系统调用号码对中的最后一个系统调用关联的号码)。

然后替换NR_syscalls值,用(现有数字增加 1)说明系统调用的总数,即在这种情况下NR_syscalls应该是 338,新值是 339。

#define NR_syscalls 339

文件 5:linux-xxx/include/linux/syscalls.h

将我们函数的原型附加到文件中。

asmlinkage long system_strcpy(char *dest,char *src);

就在#endif文件中的行之前。

文件 6:源目录根目录下的 Makefile。

打开Makefile并找到core-y定义的行并将目录添加test到该行的末尾。

core-y += kernel/ mm/ fs/ test/

现在编译内核。问题: make bzImage -j4

通过以 root 身份(或具有 root 权限)执行以下命令来安装内核: make install

重新启动系统。

要使用最近创建的系统调用,请使用:

syscall(338,dest,src);(或syscall(313,dest,src);内核 3.3+)而不是常规strcpy库函数。

#include "unistd.h"
#include "sys/syscall.h"
int main()
{
 char *dest=NULL,*src="Hello";
 dest=(char*)malloc(strlen(src)+1);
 syscall(338,dest,src);//syscall(313,dest,src); for kernel 3.3+
 printf("%s \n %s\n",src,dest);
 return 0;
}

代替 313 等数字syscall,也可以直接使用__NR_system_strcpy

这是一个通用的例子。您将需要做一些实验来查看适用于您的特定内核版本的方法。

于 2012-09-18T10:05:40.387 回答
4

上述答案不适用于内核 3.5.0 和 3.7.6,产生未定义的参考编译错误。要解决此问题,应将 linux/syscalls.h 包含在 system_strcpy.c 而不是 linux/linkage.h 中。此外,最好使用 SYSCALL_DEFINE2(strcpy, dest, src) 来定义系统调用。

于 2013-02-11T01:49:35.490 回答