【问题标题】:How to write system calls on debian/ubuntu如何在 debian/ubuntu 上编写系统调用
【发布时间】:2012-09-18 03:03:46
【问题描述】:

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

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

谁能给我指出一个干净的hello world 类程序来开发系统调用?

编辑

below answer,这是我的问题:

  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. 内核映像编译成功,但我无法调用该函数。当我用 gcc 编译它时,它会给出一个undefined reference" error。为什么?

【问题讨论】:

  • 请不要在一篇文章中提出多个问题。无论如何,您的第二个问题不属于 Stack Overflow;我建议您在superuser.com 询问
  • 我的建议是从小处着手,只需使用一个什么都不做的简单模块。然后一次添加一小块,直到它工作或崩溃。如果它崩溃了,那么你就知道是什么导致了崩溃,并且可以将相关代码放在一个问题中,询问可能导致崩溃的原因。此外,最好在虚拟机中进行内核试验,这样您就不必担心重新启动,即使内核崩溃也可以继续工作。
  • 您熟悉内核编程吗?你是把系统调用写成内核还是内核模块的一部分?
  • @askmish 我正在学习它们。我正在编写系统调用作为内核的一部分

标签: c ubuntu linux-kernel debian recovery


【解决方案1】:

这只是一个示例如何编写一个简单的内核系统调用。 考虑以下 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-x.x.x目录。

文件 1:linux-x.x.x/test/system_strcpy.c 在 linux-x.x.x 中创建一个目录,命名为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-x.x.x/test/Makefile 在您在上面创建的同一 test 目录中创建一个 Makefile 并将此行放入其中:

obj-y := system_strcpy.o

文件 3:linux-x.x.x/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 process_vm_writev sys_process_vm_writev

312 64 kcmp sys_kcmp

313 64 system_strcpy system_strcpy

3.3 版本的格式为: numberabinameentry point

文件 4:linux-x.x.x/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-x.x.x/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;
}

syscall中的313等数字也可以直接用__NR_system_strcpy代替

这是一个通用示例。您需要进行一些试验,看看哪些方法适用于您的特定内核版本。

【讨论】:

  • 优秀的答案!我现在正在尝试..与此同时,您能否更详细地解释文件 3 和文件 4(至于为什么相同的语法/语义)
  • @footy:我认为您在 64 位机器上使用的是 3.3.xx 版本的内核。在这种情况下,我必须稍微编辑一下答案。事情从 2.6 到 3.3 发生了变化。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 2013-05-19
    • 1970-01-01
    • 2010-12-15
    • 2013-07-19
    相关资源
    最近更新 更多