编译内核模块的方法与编译一般应用程序的方法略有不同. 我们会发现在内核源码树的层层目录中, 都存在有Makefile.
即这些Makefile是分层次组织的. 以往的内核版本中, 编译模块比较麻烦, 需要我们对这些Makefile做出许多更改.
2.6的内核采用了"kbuild"编译系统, 简化了这些问题. 关于kbuild, 可参考内核源码树中的 /Documentation/kbuild/modules.txt.
编译之前, 肯定是需要源文件的. 这些源文件可以放在内核源码树中, 也可以放在内核源码树之外的任何地方. 根据源文件存在的目录, 存在两种编译方法: 在源码树之中和在源码树之外.
在源码树中编译模块
官方内核模块的源代码都是按模块(驱动)类型组织的, 我们到内核源码树的drivers目录可以看到char, usb, block之类的子目录. 那么我们在内核源码树中添加文件时, 最好也遵循这些分类. 分类的规则自己灵活把握.
下面以前面的"hello, world"这个简单的模块为例, 来看看如何在内核源码树中编译模块.
1, 不新建子目录
(1) 先在内核源码树中的drivers目录编辑一个c源程序, 名为hello.c.
(2) 修改drivers目录的Makefile文件, 添加: obj-m += hello.o
(3) 重新编译内核(回到源码树根目录, 运行 $ sudo make
).
这样, 在drivers目录多出了这样几个文件: hello.mod.c, hello.mod.o, hello.o, hello.ko. hello.ko就是编译出来的模块了.
2, 新建子目录
如果源文件比较多, 可以在drivers目录中新建子目录. 还是以hello, world为例:
(1) 在内核源码树的drivers目录中新建一个hello子目录, 并将hello.c放在hello目录中.
(2) 修改drivers目录的Makefile文件, 添加: obj-m += hello/
(3) 在hello目录中新建一个Makefile文件, 内容为: obj-m += hello.o
(4) 重新编译内核(回到源码树根目录, 运行 $ sudo make
).
这样, 新生成的模块文件就位于hello目录中.
若在内核源码树中编译模块, 如果不新建子目录, 那么只需修改当前目录的Makefile, 否则应该在当前新建的子目录中新建Makefile指定编译选项, 并修改上层目录的Makefile以让kbuild能够进入新建的子目录.
|
在源码树之外编译模块
还是以上面的hello, world为例. 在当前目录有个hello.c:
(1)首先在模块代码所在的目录新建一个Makefile, 内容为:
obj-m := hello.o
(2)这样调用make命令:
$ sudo make -C /usr/local/src/kernel/linux-2.6.16.20 SUBDIRS=$PWD modules
这里/usr/local/src/kernel/linux-2.6.16.20是内核源码树所在的目录.
-C表示要求make先切换到-C指定的目录. SUBDIRS(也可以用M代替SUBDIRS)使make在编译模块之前回到当前目录.
整个编译过程实际上是执行-C指定的内核源码树的Makefile, 并通过SUBDIR指定你要编译的内核源文件的目录.
简化命令行输入
每次调用make的时候输入这些参数比较比较麻烦, 可以这样来改写Makefile以简化:
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
这样, 只需在当前目录调用 $ sudo make
就可以完成上面的工作. 调用 $ sudo make clean
将删除所有新生成的文件.
上面的Makefile是这样确定内核源码树所在的目录的: 我们先到/lib/modules目录, 会看到一些以内核版本为名的目录,
目录中有一个build文件, 它是一个符号连接, 指向内核源码树. 那么如何确定进入哪个内核版本的目录呢? 这就可以通过 $
uname -r
来确定, 它指出了当前运行内核的版本.
还可以进一步简化这个Makefile:
obj-m := hello.o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
这样不用在Makefile中一次又一次地指定内核代码树的目录.
上面的例子中只讨论了所有的代码在一个文件中的情况. 若代码分布在多个源文件中, 比如file1.c, file2.c, 生成hello.ko. 应该这样写Makefile:
obj-m := hello.o
hello-objs := file1.o file2.o
注意, 虽然我们的目的是生成.ko文件, 但在Makefile中写为.o!
|
为预编译的内核编译模块
前面都讨论的是针对当前运行的内核编译模块, 实际上, 也可以针对非当前运行的内核编译模块.比如, 我当前运行的内核版本是2.6.16, 但系统中还有2.6.12版的内核. 在不想重启来运行2.6.12版内核的情况下, 如何针对2.6.12编译模块呢?
分享到:
相关推荐
ldd3_for_linux_kernel_3.2.x
3. **Linux设备模型**:在Linux中,设备被抽象为文件,可以通过`/dev`目录下的设备文件访问。字符驱动通常对应于`c`类型的设备文件。 4. **驱动程序注册**:驱动程序必须向内核注册,通过`register_chrdev()`函数...
通讯录系统的主要功能模块包括:新联系人添加、联系人查询、联系人编辑和联系人删除。在VB中,这些功能可以通过设计用户界面(UI)控件如文本框、列表框、按钮等,配合事件驱动编程来实现。例如,当用户点击“添加”...
《ldd.rar_lld》是关于嵌入式系统中驱动程序开发的重要资源,主要涵盖了设备驱动的各个模块及其功能。ldd(Linux Device Driver)在Linux操作系统中扮演着至关重要的角色,它作为操作系统内核与硬件设备之间的桥梁,...
- 内核模块:设备驱动程序常被编写为可加载的内核模块,方便动态加载和卸载,如通过insmod、rmmod命令。 在"ldd"文件中,可能会涵盖以上提到的各个知识点的详细解释、实例代码以及常见问题的解答。学习和理解这些...
This is the examples of the linux device driver 3 edition. everyone may download it but the author has no responsibity for what may result.
标题"RTC.zip_LDD8RTC_RTC in Stop mode_RTC-787_in"暗示了我们正在讨论RTC在Kinetis MCU停止模式下的工作情况,而“RTC-787”可能是特定RTC模块的型号或代号,"in"可能表示接口或输入。下面我们将详细探讨RTC在停止...
include lddbus misc-modules misc-progs pci sbull scull scullc sculld scullp scullv short shortprint skull tty usb
《ldd3_pdf.rar》是一个压缩包,包含的是《LDd3》这本书的PDF版本,这本书是关于Linux内核驱动程序开发的经典之作。对于想要深入理解Linux系统以及进行内核驱动编程的读者来说,这本书提供了丰富的知识和实践经验。...
Linux Drivers development book. Covers basics of driers more simple than the stadard driver book of rubini
linux设备驱动3(ldd3) 源码 examples 支持 linux-2.6.32.2,源码是从网上找的,自己修改后可以在linux-2.6.32.2内核环境下编译通过.注意把Makefile中的KERNELDIR ?= /home/code/buildroot/mini2440/linux-2.6.32.2改为...
Add an environment variable. Count the number of existing ones, and then allocate up a new vector of environment strings and add ours to it.
《Linux设备驱动开发详解》(LDD3)是广受欢迎的Linux内核驱动程序开发教程,作者是Ricardo Trizio Luiz。"LDD3-examples_felltrz_linux_"这个压缩包包含了该书中的实例代码,为读者提供了一个实践和深入理解书中...
3. 在命令行中,输入`ntldd <可执行文件名>`,替换`<可执行文件名>`为你想要分析的程序。这将打印出该程序依赖的所有DLL及其版本信息。 4. 分析输出结果,查找任何可能导致运行时错误或缺失的依赖项。如果发现缺少...
《ldd3》中的模块化编程章节,为读者提供了编写可加载模块的方法,并解释了如何使用insmod、rmmod等命令来管理这些模块。 通过CHM格式的《ldd3中文版》,读者可以享受便捷的离线阅读体验。CHM文件是微软开发的一种...
该书的源码包“ldd3_examples”包含了书中所涉及的所有示例代码,是学习和实践Linux设备驱动开发的重要资源。 在Linux设备驱动程序开发中,我们首先需要理解设备驱动的基本概念。设备驱动是操作系统和硬件之间的...
ldd3将指导你如何创建可加载的内核模块,以及如何使用insmod、rmmod命令进行操作。 9. **调试技巧**:书中的示例还涵盖了如何利用内核日志、printk、kdb等工具进行驱动程序的调试。 通过研究ldd3的源码,不仅可以...
首先,书中从Linux内核的基础知识入手,包括内核模块的编译、加载和卸载,以及内核编程的基本技巧。这有助于读者建立对Linux内核运行机制的基本理解。 接着,书中详细阐述了字符设备、块设备和网络设备的驱动编写,...
ldd3书中详细阐述了Linux内核的模块化设计,这是设备驱动开发的核心。Linux内核模块可以在系统运行时加载和卸载,这为设备驱动的更新和调试带来了极大的便利。书中会介绍如何编写、编译和加载这些模块,以及如何处理...
《ldd3-examples-3.x:Linux动态链接器实战指南》 在Linux系统中,动态链接器(Dynamic Linker)扮演着至关重要的角色,它负责在程序运行时解析并加载共享库,使得多个程序可以共享同一份内存空间,节省系统资源。...