第一步, 我们需要看一下模块如何必须被建立. 模块的建立过程与用户空间的应用程序的 建立过程有显著不同; 内核是一个大的, 独立的程序, 对于它的各个部分如何组合在一起 有详细的明确的要求. 建立过程也与以前版本的内核的过程不同; 新的建立系统用起来更 简单并且产生更正确的结果, 但是它看起来与以前非常不同. 内核建立系统是一头负责的 野兽, 我们就看它一小部分. 在内核源码的 Document/kbuild 目录下发现的文件, 任何想 理解表面之下的真实情况的人都要阅读一下.

16

有几个前提, 你必须在能建立内核模块前解决. 第一个是保证你有版本足够新的编译器, 模块工具, 以及其他必要工具. 在内核文档目录下的文件 Documentation/Changes 一直列 出了需要的工具版本; 你应当在向前走之前参考一下它. 试图建立一个内核(包括它的模 块),
用错误的工具版本, 可能导致不尽的奇怪的难题. 注意, 偶尔地, 编译器的版本太新 可能会引起和太老的版本引起的一样的问题. 内核源码对于编译器做了很大的假设, 新的 发行版本有时会一时地破坏东西.

如果你仍然没有一个内核树在手边, 或者还没有配置和建立内核, 现在是时间去做了. 没 有源码树在你的文件系统上, 你无法为 2.6 内核建立可加载的模块. 实际运行为其而建立 的内核也是有帮助的( 尽管不是必要的 ).

一旦你已建立起所有东西, 给你的模块创建一个 makefile 就是直截了当的. 实际上, 对 于本章前面展示的"
hello world" 例子, 单行就够了:

obj-m := hello.o

熟悉
make , 但是对 2.6 内核建立系统不熟悉的读者, 可能奇怪这个 makefile 如何工作. 毕竟上面的这一行不是一个传统的 makefile 的样子.
答案, 当然, 是内核建立系统处理 了余下的工作. 上面的安排( 它利用了由 GNU make 提供的扩展语法 )表明有一个模块要 从目标文件 hello.o
建立. 在从目标文件建立后结果模块命名为 hello.ko.

反之, 如果你有一个模块名为 module.ko, 是来自 2 个源文件( 姑且称之为, file1.c 和
file2.c ), 正确的书写应当是:

obj-m
:= module.o

module-objs
:= file1.o file2.o

对于一个象上面展示的要工作的 makefile, 它必须在更大的内核建立系统的上下文被调用. 如果你的内核源码数位于, 假设, 你的 ~/kernel-2.6 目录, 用来建立你的模块的 make 命令( 在包含模块源码和
makefile 的目录下键入 )会是:

make -C ~/kernel-2.6 M=`pwd`
modules

这个命令开始是改变它的目录到用 -C 选项提供的目录下( 就是说, 你的内核源码目录 ). 它在那里会发现内核的顶层 makefile. 这个 M= 选项使
makefile 在试图建立模块目标前, 回到你的模块源码目录.
这个目标, 依次地, 是指在 obj-m 变量中发现的模块列表, 在我 们的例子里设成了 module.o.

键入前面的 make 命令一会儿之后就会感觉烦, 所以内核开发者就开发了一种 makefile 方式, 使得生活容易些对于那些在内核树之外建立模块的人. 这个窍门是如下书写你的 makefile:

#
If KERNELRELEASE is defined, we've been invoked from the

#
kernel build system and can use its language. ifneq ($(KERNELRELEASE),)

obj-m := hello.o

#
Otherwise we were called directly from the command

#
line; invoke the kernel build system.

else

KERNELDIR
?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd)

default:

$(MAKE)
-C $(KERNELDIR) M=$(PWD) modules

endif

再一次,
我们看到了扩展的 GNU make 语法在起作用. 这个 makefile 在一次典型的建立 中要被读 2 次. 当从命令行中调用这个 makefile , 它注意到
KERNELRELEASE 变量没有 设置. 它利用这样一个事实来定位内核源码目录, 即已安装模块目录中的符号连接指回内 核建立树. 如果你实际上没有运行你在为其而建立的内核,
你可以在命令行提供一个 KERNELDIR= 选项, 设置 KERNELDIR 环境变量, 或者重写 makefile 中设置 KERNELDIR 的 那一行.
一旦发现内核源码树, makefile 调用 default: 目标, 来运行第 2 个 make 命 令( 在 makefile 里参数化成
$(MAKE))象前面描述过的一样来调用内核建立系统. 在第 2 次读, makefile 设置 obj-m, 并且内核的 makefile 文件完成实际的建立模块工作.

这种建立模块的机制你可能感觉笨拙模糊. 一旦你习惯了它, 但是, 你很可能会欣赏这种 已经编排进内核建立系统的能力. 注意, 上面的不是一个完整的
makefile; 一个真正的 makefile 包含通常的目标类型来清除不要的文件, 安装模块等等. 一个完整的例子可以参 考例子代码目录的 makefile.

linux 编译模块的更多相关文章

  1. linux编译模块,包含了头文件却还是报undifind警告

    在编写一个自己写的gadget驱动的时候遇到一个这样的问题,编译的时候报了个警告:WARNING: "usb_composite_register" [-/my_zero.ko] ...

  2. linux 实践2.2 编译模块

    1.  理解模块原理 linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容都集成在一起,效率很高,但可扩展性和可维 ...

  3. Linux课程实践二:编译模块实现内核数据操控

    一.内核模块原理 1. Linux内核增加功能 Linux内核整体结构很庞大,包含了很多的组件,现在有两种方法将需要的功能包含进内核当中: - 静态加载:将所有的功能都编译进Linux内核. - 动态 ...

  4. linux kernel 模块多文件编译

    /*************************************************************************** * linux kernel 模块多文件编译 ...

  5. linux 编译安装PHP模块

    本文移到:http://www.phpgay.com/Article/detail/classid/6/id/54.html  linux 编译安装PHP模块 1.首先你要有你服务器上安装的PHP的版 ...

  6. Linux 内核 编译模块

    背景: 由于调试内核或者由于分区大小限制,有时候内核组件不一定完全需要编进内核中. 所以,在开发中经常将内核组件编译成为模块,等到在恰当的时机加载. 概览: Linux内核模块的编译方法有两种: 1. ...

  7. 20135218 Linux 实践二 编译模块

    20135218 姬梦馨 1.编写模块代码 模块构造函数:执行insmod或modprobe指令加载内核模块时会调用的初始化函数.函数原型必须是module_init(),括号内是函数指针 模块析构函 ...

  8. 【转】linux 编译安装nginx,配置自启动脚本

    linux 编译安装nginx,配置自启动脚本 本文章来给各位同学介绍一篇关于linux 编译安装nginx,配置自启动脚本教程,希望有需要了解的朋友可一起来学习学习哦. 在公司的suse服务器装ng ...

  9. 如何增强 Linux 系统的安全性,第一部分: Linux 安全模块(LSM)简介

    http://www.ibm.com/developerworks/cn/linux/l-lsm/part1/ 1.相关背景介绍:为什么和是什么 近年来Linux系统由于其出色的性能和稳定性,开放源代 ...

随机推荐

  1. Elasticsearch 启动需要密码?

    vagrant@homestead:~$ systemctl disable elasticsearch.service Synchronizing state of elasticsearch.se ...

  2. 类似淘宝五星点评 ,Jquery实现代码

    <!--默认五星,根据鼠标点击判断--> <!DOCTYPE html><html lang="en"><head> <met ...

  3. JVM学习篇章(一)

    熟悉Java开发的同学,应该都知道jvm是什么,---它就是Java虚拟机,今天我们就学习一下:  内存分配原则:  常用的监控命令

  4. Adapter小练习

    Aapter的继承关系图: Android中Adapter的是数据和视图之间的桥梁,数据在adapter中做处理,然后显示到视图上面. 一.ArrayAdapter适配器 java代码: import ...

  5. Java中的四种引用(强引用、软引用、弱引用、虚引用)

    以下内容摘自<深入理解Java虚拟机 JVM高级特性与最佳实践>第2版,强烈推荐没有看过的同学阅读,读完的感觉就是"原来学的都是些什么瘠薄东西(╯‵□′)╯︵┴─┴" ...

  6. More Effective C++: 04效率

    16:牢记80-20准则 80-20准则说的是大约20%的代码使用了80%的程序资源:大约20%的代码耗用了大约80%的运行时间:大约20%的代码使用了80%的内存:大约20%的代码执行80%的磁盘访 ...

  7. Git同步Python代码

    之前我们都是将代码保存到本地目录, 然后再上传到Git中,但如果针对在pycharm中的代码,就要换另一种方式了,下面简单介绍一下. 1.打开pycharm主界面,选择菜单栏VCS---checkou ...

  8. Oracle安装 卸载 和常见问题

    Oracle的安装   全局数据库名:orcl  口令:orcl 或者以第三方工具SQLplus为例 系统用户:sys 和 system  练习账户:scott (密码:tiger) 登录账户为:sy ...

  9. python 编码和解码

  10. python3中的zip函数

    zip函数的作用: zip函数接受任意多个可迭代对象作为参数,将对象中对应的元素打包成一个tuple,然后返回一个可迭代的zip对象. 这个可迭代对象可以使用循环的方式列出其元素 若多个可迭代对象的长 ...