【问题标题】:Error: conflicting types when trying to make a simple syscall错误:尝试进行简单的系统调用时类型冲突
【发布时间】:2020-05-16 14:04:07
【问题描述】:

我是 Linux 编程的新手,我正在尝试按照本指南松散地实现一个简单的系统调用:https://medium.com/anubhav-shrimal/adding-a-hello-world-system-call-to-linux-kernel-dad32875872。在我的 linux 内核目录中,我创建了一个名为 my_syscall 的新目录。在那个目录中,我创建了my_syscall.c。这里是my_syscall.c

#include <linux/syscalls.h>
#include <linux/kernel.h>

asmlinkage long sys_my_syscall(int i) {
   prink(KERN_INFO "This is the system call.");
   return(0);
}

然后,我在my_syscall 目录中创建了一个Makefile,其中包含一行:

obj-y := my_syscall.o

然后我将内核目录中Makefile中的这一行编辑为:

core-y         += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ my_syscall/

然后,在目录linux-5.4.15/arch/x86/entry/syscalls 中,我编辑了syscall_64.tbl 以在最后包含以下行:

548     64         my_syscall          sys_my_syscall

最后,在linux-5.4.15/include/linux 目录中,我编辑了syscalls.h 文件,将这一行包含在#endif 之前:

asmlinkage long sys_my_syscall(int i);

现在,当我运行命令 sudo make 时,很快就会遇到以下错误:

./arch/x86/include/generated/asm/syscalls_64.h:2664:19: error: conflicting types for 'sys_my_syscall'
__SYSCALL_64(548, sys_my_syscall, )

arch/x86/entry/syscall_64.c:18:60: note: in definition of macro '__SYSCALL-64'
  #define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);

In file included from arch/x86/entry/syscall_64.c:7:0:
./include/linux/syscalls.h:1423:17: note: previous declaration of 'sys_my_syscall' was here
 asmlinkage long sys_my_syscall(int i);
                 ^
make[3]: *** [arch/x86/entry/syscall_64.o] Error 1
make[2]: *** [arch/x86/entry] Error 2
make[1]: *** [arch/x86] Error 2
make: *** [sub-make] Error 2

我不知道如何处理这个错误。由于类型冲突错误,我想我在某个地方以不同的方式声明了系统调用,但在 my_syscall.csyscalls.h 文件中,声明是相同的。这些是声明系统调用的仅有的两个文件,但它也在syscall_64.tbl 中命名,这似乎是 linux 试图指向我的地方。但是,当我直接按照指南进行操作时,我看不出我在表格中声明它的方式有什么问题。对此的任何帮助将不胜感激!

信息:

内核版本:5.4.15

Linux 发行版:Ubuntu 14

【问题讨论】:

标签: linux linux-kernel system-calls


【解决方案1】:

我刚刚更改了 syscall_64.tbl 中定义系统调用号的位置。

而不是这个:

548     64         my_syscall          sys_my_syscall

这是我写的:

436     common     my_syscall          __x64_sys_my_syscall

Screen Capture of my configuration

成功了。

【讨论】:

    【解决方案2】:

    我正在做类似的事情并得到完全相同的错误。

    为我解决的错误是将 syscall_64.tbl 表条目的最后一部分从“sys_my_syscall”更改为“__x64_sys_my_syscall”。如果向上滚动,其他条目具有相同的前缀。在我进行更改后,内核开始编译。

    【讨论】:

    • 我之前也试过这个。内核编译了更长的时间,但最终弹出另一个错误
    【解决方案3】:
        #include <linux/syscalls.h>
        #include <linux/kernel.h>
    
        SYSCALL_DEFINE1(my_syscall, int, i)
        {
           printk(KERN_INFO "This is the system call (param %d).\n", i);
           return(0);
        }
    

    对于内核 5,请尝试在“my_syscall”之前删除“sys_”并尝试。它对我有用

    【讨论】:

      【解决方案4】:

      一些架构(包括 x86-64)使用 系统调用包装器 来调用真正的系统调用处理程序。要定义真正的系统调用处理程序及其包装器(对于使用系统调用包装器的架构),请在系统调用处理程序的主体之前使用SYSCALL_DEFINE&lt;n&gt; 宏之一。 SYSCALL_DEFINE&lt;n&gt;宏的参数是函数名,后跟&lt;n&gt;成对的``type, param''作为函数参数。

      您的sys_my_syscall syscall 处理函数只有一个参数,因此请在函数体前使用SYSCALL_DEFINE1 宏:

      #include <linux/syscalls.h>
      #include <linux/kernel.h>
      
      SYSCALL_DEFINE1(sys_my_syscall, int, i)
      {
         printk(KERN_INFO "This is the system call (param %d).\n", i);
         return(0);
      }
      

      【讨论】:

      • 我试图这样做,但它导致与以前相同的错误
      • 您在 "include/linux/syscalls.h" 之前插入了 #endif 的哪个 asmlinkage long sys_my_syscall(int i); 行?它需要介于 #ifndef CONFIG_ARCH_HAS_SYSCALL_WRAPPER 和匹配的 #endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ 之间。
      • 这可能是我的问题。我在syscalls.h 文件中的最后一个#endif 之前插入了函数
      【解决方案5】:

      我最终放弃了尝试在内核 5 中实现这一点。不幸的是,其他解决方案都没有导致我的内核编译。我回滚了我的内核并按照here 的步骤操作。这导致系统调用正常工作。我不确定如何在内核 5+ 中实现此功能。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-07
        • 2013-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多