📄 ch02s04.html
字号:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>2.4. 编译和加载-Linux设备驱动第三版(中文版)-开发频道-华星在线</title>
<meta name="description" content="驱动开发-开发频道-华星在线" />
<meta name="keywords" content="Linux设备驱动,中文版,第三版,ldd,linux device driver,驱动开发,电子版,程序设计,软件开发,开发频道" />
<meta name="author" content="华星在线 www.21cstar.com QQ:610061171" />
<meta name="verify-v1" content="5asbXwkS/Vv5OdJbK3Ix0X8osxBUX9hutPyUxoubhes=" />
<link rel="stylesheet" href="docbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.69.0">
<link rel="start" href="index.html" title="Linux 设备驱动 Edition 3">
<link rel="up" href="ch02.html" title="第 2 章 建立和运行模块">
<link rel="prev" href="ch02s03.html" title="2.3. 内核模块相比于应用程序">
<link rel="next" href="ch02s05.html" title="2.5. 内核符号表">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr><th colspan="3" align="center">2.4. 编译和加载</th></tr>
<tr>
<td width="20%" align="left">
<a accesskey="p" href="ch02s03.html">上一页</a> </td>
<th width="60%" align="center">第 2 章 建立和运行模块</th>
<td width="20%" align="right"> <a accesskey="n" href="ch02s05.html">下一页</a>
</td>
</tr>
</table>
<hr>
</div>
<div class="sect1" lang="zh-cn">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="CompilingandLoading.sect1"></a>2.4. 编译和加载</h2></div></div></div>
<p> 本章开头的 "hello world" 例子包含了一个简短的建立并加载模块到系统中去的演示. 当然, 整个过程比我们目前看到的多. 本节提供了更多细节关于一个模块作者如何将源码转换成内核中的运行的子系统.
</p>
<div class="sect2" lang="zh-cn">
<div class="titlepage"><div><div><h3 class="title">
<a name="CompilingModules.sect2"></a>2.4.1. 编译模块</h3></div></div></div>
<p> 第一步, 我们需要看一下模块如何必须被建立. 模块的建立过程与用户空间的应用程序的建立过程有显著不同; 内核是一个大的, 独立的程序, 对于它的各个部分如何组合在一起有详细的明确的要求. 建立过程也与以前版本的内核的过程不同; 新的建立系统用起来更简单并且产生更正确的结果, 但是它看起来与以前非常不同. 内核建立系统是一头负责的野兽, 我们就看它一小部分. 在内核源码的 Document/kbuild 目录下发现的文件, 任何想理解表面之下的真实情况的人都要阅读一下. </p>
<p> 有几个前提, 你必须在能建立内核模块前解决. 第一个是保证你有版本足够新的编译器, 模块工具, 以及其他必要工具. 在内核文档目录下的文件 Documentation/Changes 一直列出了需要的工具版本; 你应当在向前走之前参考一下它. 试图建立一个内核(包括它的模块), 用错误的工具版本, 可能导致不尽的奇怪的难题. 注意, 偶尔地, 编译器的版本太新可能会引起和太老的版本引起的一样的问题. 内核源码对于编译器做了很大的假设, 新的发行版本有时会一时地破坏东西. </p>
<p> 如果你仍然没有一个内核树在手边, 或者还没有配置和建立内核, 现在是时间去做了. 没有源码树在你的文件系统上, 你无法为 2.6 内核建立可加载的模块. 实际运行为其而建立的内核也是有帮助的( 尽管不是必要的 ). </p>
<p> 一旦你已建立起所有东西, 给你的模块创建一个 makefile 就是直截了当的. 实际上, 对于本章前面展示的" hello world" 例子, 单行就够了: </p>
<pre class="screen">
obj-m := hello.o
</pre>
<p> 熟悉 make , 但是对 2.6 内核建立系统不熟悉的读者, 可能奇怪这个 makefile 如何工作. 毕竟上面的这一行不是一个传统的 makefile 的样子. 答案, 当然, 是内核建立系统处理了余下的工作. 上面的安排( 它利用了由 GNU make 提供的扩展语法 )表明有一个模块要从目标文件 hello.o 建立. 在从目标文件建立后结果模块命名为 hello.ko. </p>
<p> 反之, 如果你有一个模块名为 module.ko, 是来自 2 个源文件( 姑且称之为, file1.c 和 file2.c ), 正确的书写应当是: </p>
<pre class="screen">
obj-m := module.o
module-objs := file1.o file2.o
</pre>
<p> 对于一个象上面展示的要工作的 makefile, 它必须在更大的内核建立系统的上下文被调用. 如果你的内核源码数位于, 假设, 你的 ~/kernel-2.6 目录, 用来建立你的模块的 make 命令( 在包含模块源码和 makefile 的目录下键入 )会是: </p>
<pre class="screen">
make -C ~/kernel-2.6 M=`pwd` modules
</pre>
<p> 这个命令开始是改变它的目录到用 -C 选项提供的目录下( 就是说, 你的内核源码目录 ). 它在那里会发现内核的顶层 makefile. 这个 M= 选项使 makefile 在试图建立模块目标前, 回到你的模块源码目录. 这个目标, 依次地, 是指在 obj-m 变量中发现的模块列表, 在我们的例子里设成了 module.o. </p>
<p> 键入前面的 make 命令一会儿之后就会感觉烦, 所以内核开发者就开发了一种 makefile 方式, 使得生活容易些对于那些在内核树之外建立模块的人. 这个窍门是如下书写你的 makefile: </p>
<pre class="screen">
# 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
</pre>
<p> 再一次, 我们看到了扩展的 GNU make 语法在起作用. 这个 makefile 在一次典型的建立中要被读 2 次. 当从命令行中调用这个 makefile , 它注意到 KERNELRELEASE 变量没有设置. 它利用这样一个事实来定位内核源码目录, 即已安装模块目录中的符号连接指回内核建立树. 如果你实际上没有运行你在为其而建立的内核, 你可以在命令行提供一个 KERNELDIR= 选项, 设置 KERNELDIR 环境变量, 或者重写 makefile 中设置 KERNELDIR 的那一行. 一旦发现内核源码树, makefile 调用 default: 目标, 来运行第 2 个 make 命令( 在 makefile 里参数化成 $(MAKE))象前面描述过的一样来调用内核建立系统. 在第 2 次读, makefile 设置 obj-m, 并且内核的 makefile 文件完成实际的建立模块工作. </p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -