Linux如何将驱动文件编译成独立的模块或者编译到内核?

编译成独立的模块

首先,说下如何编译成独立的模块

需要使用如下命令

make modules

接下来对该指令进行说明

make modules 命令的执行路径只能是内核源码顶层目录,执行结果是:读取内核源码顶层目录中的 Makefile 文件,找到里面定义的 modules 目标。

通常,我们写一个驱动文件,不会直接放到linux的目录里,而是放在我们自定义的一些目录中,比如我们自定义一个目录test,里面有个要编译的驱动文件led.c,这时候,如果我们想要将led.c编译成独立的模块,也就是编译成.ko文件的话,就可以使用make modules,但是,因为要读取linux内核源码顶层的makefile,所以,需要使用-C来指定该Makefile的位置,也就是如下命令:

make -C 内核顶层Makefile的路径 modules

另外,上面说了,执行make modules时会到linux源码顶层目录的Makefile文件里去找modules目标,但是,我们一般不会直接去修改顶层的Makefile,要不然每次增加一个模块就改一次,那样的话,就太麻烦了。所以,我们可以使用另外一个参数M,来指定要编译的模块源码,于是,又完善下该指令,如下:

make -C 内核顶层Makefile的路径 M=当前路径 modules

这就是将驱动源码编译成独立模块的方式。

更多参考:

linux make modules 命令详解-CSDN博客

简单实例讲解linux的module模块编译步骤 - aaronGao - 博客园 (cnblogs.com)

Linux模块文件如何编译到内核和独立编译成模块?_linux make modules能指定defconfig吗-CSDN博客

后续根据实践来完善。

关于.ko文件

参考:Linux下编写和加载 .ko 文件(驱动模块文件)_qt 加载 .ko-CSDN博客

一、.ko 文件介绍

.ko文件是kernel object文件(内核模块),该文件的意义就是把内核的一些功能移动到内核外边, 需要的时候插入内核,不需要时卸载。
 

二、优点

(1)这样可以缩小内核体积;

(2)使用方便。

三、.ko文件一般的用处

作为一个功能模块,需要使用时,直接插入运行就行。如在imx6上连接模拟摄像头,先运行模拟摄像头对应的驱动模块 camera.ko文件,然后对应的工程执行文件运行就行。

四、使用.ko 文件

1、加载驱动模块test.ko

(1)方法一 
进入test.ko驱动模块文件所在的目录,然后直接   insmod  test.ko 

(2)方法二 
将test.ko文件拷贝到/lib/module/#uname-r#/目录下,这里,#uname -r#意思是,在终端中输入uname -r后显示的内核版本及名称,例如mini2440中#uname-r#就是2.6.32.2-FriendlyARM。

然后 depmod(会在/lib/modules/#uname -r#/目录下生成modules.dep和modules.dep.bb文件,表明模块的依赖关系) 
最后 modprobe test(注意这里无需输入.ko后缀) 即可。

注:两种方法的区别

modprobe和insmod类似,都是用来动态加载驱动模块的,区别在于modprobe可以解决load module时的依赖关系,它是通过/lib/modules/#uname -r/modules.dep(.bb)文件来查找依赖关系的;而insmod不能解决依赖问题。也就是说,如果你确定你要加载的驱动模块不依赖其他驱动模块的话,既可以insmod也可以modprobe,当然insmod可以在任何目录下执行,更方便一些。而如果你要加载的驱动模块还依赖其他ko驱动模块的话,就只能将模块拷贝到上述的特定目录,depmod后再modprobe。

2、查看已加载的驱动模块列表

在任何目录下输入命令

lsmod

3、卸载驱动模块

在任何目录下, 输入命令

rmmod <module_name>  

注:“module_name”是lsmod显示的模块名称,而不是对应的ko文件名

编译到内核

直接参考:

嵌入式Linux驱动开发 02:将驱动程序添加到内核中_ip驱动怎么集成到linux内核-CSDN博客

linux设备驱动程序——将驱动程序编译进内核 - 牧野星辰 - 博客园 (cnblogs.com)

后续根据实践来完善。

内核编译obj-m和obj-y的区别

在内核编译时,主要涉及以下文件:

kernel/arch/arm/configs/*.defconfig

kernel/driver/*/Makefile

kernel/driver/*/Kconfig

如果我们想要往内核中增加新的节点,还要涉及到设备树文件,kernel/arch/arm/boot/dts/

在进行模块编译时,主要有两个选项,obj-m和obj-y,而与内核密切相关的是obj-y选项,下面对两者之间的区别简单总结一下。

以test.c文件为例:

obj-m += test.o

obj-y += test.o

其中:

obj-m表示把文件test.o作为"模块"进行编译,不会编译到内核,但是会生成一个独立的 "test.ko" 文件;

obj-y表示把test.o文件编译进内核;

如何抉择? 

哪些驱动适合编译到内核中?哪些驱动适合编译成独立的模块?

在Linux系统中,驱动程序的编译方式主要分为两种:编译进内核和编译成独立的模块。以下将详细介绍哪些驱动适合编译到内核中以及哪些适合编译成独立模块:

适合编译到内核中的驱动

  1. 关键性驱动:对于系统启动和运行至关重要的驱动,如CPU、内存、PCI总线等驱动,通常需要编译进内核。这些驱动在系统启动时必须立即可用,以确保硬件能够正常工作。

  2. 性能敏感型驱动:对于需要高性能响应的驱动,如网络驱动、存储驱动等,编译进内核可以减少加载和卸载的时间开销,提高系统的整体性能。

  3. 稳定性要求高的驱动:对于需要高稳定性的驱动,如文件系统驱动、设备驱动等,编译进内核可以确保它们的稳定性,避免因模块加载失败导致的系统不稳定。

适合编译成独立模块的驱动

  1. 非关键性驱动:对于一些非关键性的驱动,如某些外设的驱动,可以选择编译成独立模块。这样可以根据需要动态加载和卸载,节省内核空间。

  2. 开发阶段驱动:在开发过程中,为了方便调试和测试,可以将驱动编译成独立模块。这样可以在不重启系统的情况下进行驱动的更新和替换。

  3. 第三方驱动:对于由第三方提供的驱动,由于可能与内核的其他部分存在兼容性问题,将其编译成独立模块可以避免潜在的冲突和问题。

总的来说,选择将驱动编译到内核中还是编译成独立模块,需要根据具体的应用场景和需求来决定。在大多数情况下,为了保持系统的灵活性和可维护性,推荐将驱动编译成独立模块。

驱动程序自启动

在Linux系统中,实现驱动程序自启动通常涉及到以下几种方法:

  1. 编辑/etc/rcS文件

            
    shell复制代码
    /sbin/insmod /lib/mmcsd_core.o
    /sbin/insmod /lib/mmcsd_slot.o
    /sbin/insmod /lib/mmcsd_disk.o
    1. 这是一个常见的方法,用于在系统启动时自动加载驱动或启动应用程序。你需要使用文本编辑器(如vi)打开/etc/init.d/rcS文件,并在其中添加你的驱动加载命令或脚本。例如,如果你想在启动时加载一个名为mmcsd的SD卡驱动模块,可以在文件中添加如下行:

    2. 保存并退出后,这些命令将在系统每次启动时自动执行。

  2. 利用systemd服务单元文件

    1. Systemd是现代Linux发行版中广泛使用的系统和服务管理器。你可以通过创建自定义的systemd服务单元文件来实现驱动程序的自启动。首先,在/etc/systemd/system/目录下创建一个.service文件,例如mydriver.service。然后,在该文件中定义你的服务,包括启动脚本和依赖关系。最后,使用systemctl enable mydriver.service命令来设置该服务在开机时自动启动。

  3. 修改/etc/modules文件

    1. 对于一些简单的内核模块,你也可以将它们添加到/etc/modules文件中。这样,当系统启动时,这些模块将自动被加载。只需将模块名称(不带.ko后缀)添加到该文件中的一行即可。

  4. 配置udev规则

    1. 如果驱动程序与特定的硬件设备相关联,你还可以使用udev规则来实现自启动。通过在/etc/udev/rules.d/目录下创建或修改udev规则文件,你可以指定当检测到特定设备时自动加载相应的驱动程序模块。

总的来说,以上方法均适用于Linux系统中驱动程序的自启动设置。选择具体方法时,需根据实际需求、系统环境以及驱动程序的特性进行权衡。同时,建议在进行任何系统级更改前备份相关配置文件以防不测。

linux中驱动需要自启动吗?

在Linux系统中,驱动程序是否需要自启动取决于具体的应用场景和需求。以下是一些关于Linux驱动自启动的考虑因素:

  1. 系统稳定性:某些驱动程序对于系统的稳定运行至关重要,如网络驱动、存储驱动等。这些驱动通常需要在系统启动时自动加载,以确保系统功能的正常运行。

  2. 用户便利性:对于需要频繁使用的设备或应用程序,将其驱动程序设置为自启动可以提供更好的用户体验。例如,USB存储设备、打印机等外设的驱动,如果设置为自启动,则用户无需每次手动加载。

  3. 资源管理:自启动驱动可能会占用一定的系统资源,如内存和CPU。因此,在决定是否将某个驱动设置为自启动时,需要考虑其对系统资源的影响。对于不常用的驱动,可以选择在需要时手动加载,以节省系统资源。

  4. 安全性:自启动驱动可能会带来潜在的安全风险。恶意软件可能利用自启动驱动来执行未经授权的操作。因此,在设置自启动驱动时,需要确保其来源可靠,并定期进行安全检查。

  5. 依赖关系:某些驱动程序之间存在依赖关系。在设置自启动驱动时,需要确保所有相关的依赖驱动都已正确安装和配置,否则可能导致系统无法正常启动或功能异常。

  6. 兼容性:不同的Linux发行版和内核版本可能存在兼容性问题。在设置自启动驱动时,需要确保所选的驱动与当前系统环境兼容,以避免出现兼容性问题。

综上所述,Linux中驱动是否需要自启动应根据具体需求和场景来决定。对于关键性和常用性的驱动,建议设置为自启动以提高系统稳定性和用户便利性;而对于不常用或存在潜在风险的驱动,则可以选择手动加载或根据需要进行配置。同时,在设置自启动驱动时,还需要注意资源管理、安全性、依赖关系以及兼容性等方面的问题。

补充思考

在windows下,我们安装某个设备的驱动,为什么直接安装驱动就行,而不需要编译整个操作系统?

在Windows操作系统中,安装设备驱动通常不需要编译整个操作系统。以下是对这一现象的详细解释:

  1. 驱动程序的作用

    1. 驱动程序是硬件与操作系统之间的桥梁,它允许操作系统识别和控制硬件设备。

    2. 驱动程序提供了必要的接口和指令集,使得操作系统能够与硬件进行通信和交互。

  2. 驱动程序的独立性

    1. 驱动程序是独立于操作系统核心组件之外的软件模块。它们可以在不修改或重新编译操作系统的情况下进行安装、更新或卸载。

    2. 这种独立性使得驱动程序可以针对特定硬件进行优化和定制,而不影响操作系统的稳定性和其他功能。

  3. 驱动程序的预编译

    1. 驱动程序由硬件厂商提供,并在发布前已经在各种操作系统上进行了编译和测试。这意味着用户无需在安装时再次编译驱动程序。

    2. 安装驱动程序的过程通常包括复制文件到指定目录、在注册表中注册相关信息以及可能的初始化配置等步骤。

  4. 操作系统的模块化设计

    1. Windows操作系统采用模块化设计,将不同的功能和服务划分为独立的模块或组件。这种设计使得操作系统可以灵活地加载和卸载这些模块,而无需重新编译整个系统。

    2. 驱动程序作为这些模块之一,可以在运行时被动态加载和卸载,从而支持即插即用(PnP)功能。

  5. 兼容性和稳定性

    1. 由于驱动程序是独立于操作系统核心组件之外的,因此它们的更新和更改不会直接影响操作系统的稳定性和其他功能。这有助于保持系统的兼容性和稳定性。

    2. 同时,硬件厂商可以根据需要发布针对不同操作系统版本的驱动程序,以确保其硬件设备在不同平台上的最佳性能和兼容性。

综上所述,在Windows操作系统中,安装设备驱动通常不需要编译整个操作系统。这是因为驱动程序是独立于操作系统核心组件之外的软件模块,它们可以在不修改或重新编译操作系统的情况下进行安装、更新或卸载。同时,Windows操作系统的模块化设计和驱动程序的预编译特性也使得这一过程更加简单和高效。

为什么U盘插入后就有这个设备了,拔掉后就没了,我们可以在设备管理器中看到这个过程,这个过程也不需要去重编译内核或者根文件系统?

U盘插入后就有这个设备了,拔掉后就没了,我们可以在设备管理器中看到这个过程,这个过程也不需要去重编译内核或者根文件系统。以下是对这一现象的详细解释:

  1. 即插即用特性:U盘设计为即插即用的外部存储设备,其驱动程序通常已经预装在操作系统中。当U盘插入电脑时,操作系统能够自动识别并加载相应的驱动程序,从而使U盘成为可访问的设备。

  2. 动态加载和卸载:当U盘插入时,操作系统会动态加载U盘的驱动程序,并将U盘作为一个新的设备节点添加到系统中。当U盘被拔出时,操作系统会检测到这一事件,并动态卸载U盘的驱动程序,同时从系统中移除该设备节点。

  3. 设备管理器的作用:设备管理器是Windows操作系统中的一个工具,用于显示和管理计算机上的硬件设备。当U盘插入或拔出时,设备管理器会实时更新设备列表,以反映当前的硬件状态。因此,我们可以在设备管理器中看到U盘插入和拔出的过程。

  4. 无需重编译内核或根文件系统:由于U盘的驱动程序是预先安装在操作系统中的,并且支持动态加载和卸载,因此我们不需要在每次插入或拔出U盘时都重新编译内核或根文件系统。这大大简化了U盘的使用过程,并提高了系统的响应速度。

综上所述,U盘插入后就有这个设备了,拔掉后就没了,我们可以在设备管理器中看到这个过程,这个过程也不需要去重编译内核或者根文件系统。这是由于U盘的即插即用特性、动态加载和卸载机制以及设备管理器的实时更新功能共同作用的结果。

猜你喜欢

转载自blog.csdn.net/qq_28576837/article/details/142790697