Linux kernel Linux不支持在现有Linux设置上安装二进制驱动程序的分发的技术原因是什么?

Linux kernel Linux不支持在现有Linux设置上安装二进制驱动程序的分发的技术原因是什么?,linux-kernel,linux-device-driver,Linux Kernel,Linux Device Driver,任何Linux内核模块都可以使用EXPORT\u Symbol指令将符号放入公共符号表中。那么,为什么认为安装二进制驱动程序(您没有使用本地头文件在本地编译)是非常规的呢?内核将导出合理的驱动程序需要访问的所有符号。驱动程序将导出其所有入口点。所以它的二进制应该是可安装的,对吗 我看到一些网站给出了下载二进制驱动程序并安装它的说明,但大多数专家说Linux并不真正支持这一点。您真的应该只使用内核中上游的驱动程序。或者至少您应该下载源代码并在本地编译,然后安装它。为什么?因为内核API不稳定。这意

任何Linux内核模块都可以使用EXPORT\u Symbol指令将符号放入公共符号表中。那么,为什么认为安装二进制驱动程序(您没有使用本地头文件在本地编译)是非常规的呢?内核将导出合理的驱动程序需要访问的所有符号。驱动程序将导出其所有入口点。所以它的二进制应该是可安装的,对吗


我看到一些网站给出了下载二进制驱动程序并安装它的说明,但大多数专家说Linux并不真正支持这一点。您真的应该只使用内核中上游的驱动程序。或者至少您应该下载源代码并在本地编译,然后安装它。为什么?

因为内核API不稳定。这意味着,即使在内核树的连续小修改之间,也可能存在细微的API差异(例如内部结构的布局更改)。更糟糕的是,没有简单的方法来跟踪这些更改-可以轻松地将版本控制信息添加到函数中(没有太多),但尝试在内核中的每个内部数据结构中添加版本控制信息将是徒劳的-理论上,任何模块都可以访问内核中的任何数据结构,没有内部API隔离屏障(例如用户/内核空间边界,这在API方面非常稳定)

为了说明一个问题,假设您有一个如下所示的现有内核API:

struct s {
     int foo;
     int bar;
};

void exported_symbol(struct s *s_ptr);
然后,有人继续对代码进行了一些修改,调整为:

struct s {
    const char *funny_name;
    int foo;
    int bar;
};

void exported_symbol(struct s *s_ptr);
二进制驱动程序是否仍会加载(可以强制加载)?是的,会的。驱动程序会按预期工作吗?很可能不会,可能会导致整个系统崩溃


即使二进制模块与内核版本完全匹配,仍有另一个障碍需要考虑,即内核构建配置的差异(如在代码源树中由<代码> .CONFIG文件定义的,并且可以通过<代码> /PRO/CONFIG(.gz)在大多数设备上进行检查。如编译器所见,数据结构可能会因变量集的不同而发生相当大的变化(查看

linux/timer.h
了解一个广泛使用的API示例,该API对内核构建配置非常敏感)。

有安装二进制文件的方法,例如。,使用DKMS——它为特定驱动程序的内核构建一个二进制接口。现代Linux内核采用Modus版本,如果驱动程序不是为特定内核构建的,则会阻碍其加载,尽管有解决方法。您还应该添加,结构成员还依赖于通过
#ifdef
s编译它所使用的配置,因此即使是相同的内核版本也可以有多个不同的结构成员组合。True。添加了相关的段落。如果是这样的话会怎么样:内核头文件有:int foobar;无效导出符号(int foobar);但我的驱动程序是用一个头编译的,头有:char foobar;好的,如果是这样的话会怎么样:/*内核头有这个/int foobar;无效导出_符号(int foobar);/但我的驱动程序是用带有*/char foobar的头编译的;在这种情况下,insmod链接器会发现不兼容吗?我怀疑它会,但我个人还没有尝试过。