第一步, 我们需要看一下模块如何必须被建立. 模块的建立过程与用户空间的应用程序的 建立过程有显著不同; 内核是一个大的, 独立的程序, 对于它的各个部分如何组合在一起 有详细的明确的要求. 建立过程也与以前版本的内核的过程不同; 新的建立系统用起来更 简单并且产生更正确的结果, 但是它看起来与以前非常不同. 内核建立系统是一头负责的 野兽, 我们就看它一小部分. 在内核源码的 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. Markdown Linux

    如何在Linux下使用Markdown进行文档工作 学习于: http://www.ituring.com.cn/article/10044 Markdown 官网: http://daringfir ...

  2. Java8中的LocalDateTime工具类

    网上搜索了半天都没有找到Java8的LocalDateTime的工具类,只好自己写了一个,常用功能基本都有.还在用Date的Java同道该换换了. 个人项目地址:https://github.com/ ...

  3. 2019-6-23-WPF-网络-request-的-read-方法不会返回

    title author date CreateTime categories WPF 网络 request 的 read 方法不会返回 lindexi 2019-06-23 11:26:26 +08 ...

  4. HDU-1160_FatMouse's Speed

    FatMouse's Speed Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Sp ...

  5. 【NS2】How to remove Cygwin completely from Windows

    How to remove Cygwin completely from Windows 9th September 2012. 31243 views. Software Remember need ...

  6. ELK2之ELK的语法学习

    1.回顾 (1)es是什么? es是基于Apache Lucene的开源分布式(全文)搜索引擎,提供简单的RESTful API来隐藏Lucene的复杂性. es除了全文搜索引擎之外,还可以这样描述它 ...

  7. Cacti 加入多台主机带宽汇聚

            前面我写了一个cacti加入主机带宽监控的博客.能够參考http://blog.csdn.net/dai451954706/article/details/35272465 .有时可能 ...

  8. Gym - 101480D_Digit Division

    题意:输入n,m,将n分段,每一段都可以被m整除,有多少种方法. 题解:找到n最多可以分成多少段,1段1中分法,2段2中分法,3段4种分法--计算可知若有x段则2^x-1种分法. 注意:如果n无法被m ...

  9. QQ 聊天机器人API

    QQ机器人是腾讯陆续推出的的人工智能聊天机器人的总称. 都说小Q妹妹聪明好学,我们能够教她说话.也能够请他帮忙查询邮编.手机号,或者解释成语.翻译成语,据说她还会查询手机号码归属地.应用科学计算器. ...

  10. javax.websocket.Session的一个close异常记录

    一刷新页面就报错如下: Connection closed 四月 10, 2018 11:20:18 上午 org.apache.tomcat.websocket.pojo.PojoEndpointB ...