📄 x204.html
字号:
<HTML
><HEAD
><TITLE
>编译内核模块</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="The Linux Kernel Module Programming Guide"
HREF="index.html"><LINK
REL="UP"
TITLE="Hello World"
HREF="c143.html"><LINK
REL="PREVIOUS"
TITLE="Hello, World (part 1): The Simplest Module"
HREF="x145.html"><LINK
REL="NEXT"
TITLE="Hello World (part 2)"
HREF="hello2.html"></HEAD
><BODY
CLASS="SECT1"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>Linux内核驱动模块编程指南 (内核版本2.2, 2.4)</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="x145.html"
ACCESSKEY="P"
>返回</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>第二章. Hello World</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="hello2.html"
ACCESSKEY="N"
>继续</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="SECT1"
><H1
CLASS="SECT1"
><A
NAME="AEN204"
></A
>2.2. 编译内核模块</H1
><P
>内核模块在用gcc编译时需要使用特定的参数。另外,一些宏同样需要定义。
这是因为在编译成可执行文件和内核模块时,内核头文件起的作用是不同的。
你可以用gcc的 <TT
CLASS="OPTION"
>-D</TT
> 选项定义宏,或使用 <TT
CLASS="LITERAL"
>#define</TT
> 预处理命令。我们会在这章详细讨论这方面的内容来成功的编译我们的内核模块。</P
><P
></P
><UL
><LI
><P
><TT
CLASS="OPTION"
>-c</TT
>: 一个内核模块不是一个独立的可执行文件,而是一个内核在运行时用insmod动态连结的目标文件。所以,内核应该在编译时使用 <TT
CLASS="OPTION"
>-c</TT
> 选项。</P
></LI
><LI
><P
><TT
CLASS="OPTION"
>-O2</TT
>: 内核使用了大量的内联函数,所以模块也应该在编译时大开优化选项。否则,一些汇编的宏调用将会被编译器错误的理解为系统调用。这将导致
加载模块失败,因为内核中并不存在这样的函数接口。</P
></LI
><LI
><P
><TT
CLASS="OPTION"
>-W -Wall</TT
>: 一个编程上的错误将会使你的系统崩溃。你应该始终打开编译警告选项,不仅是在编译模块时。</P
></LI
><LI
><P
><TT
CLASS="OPTION"
>-isystem /lib/modules/`uname -r`/build/include</TT
>: 你必须使用加载你的模块的内核的头文件,而不是默认的内核头文件 <TT
CLASS="FILENAME"
>/usr/include/linux</TT
>。</P
></LI
><LI
><P
><TT
CLASS="VARNAME"
>-D__KERNEL__</TT
>: 定义这个宏通知编译器将要编译的代码在内核态运行,而不是用户态。</P
></LI
><LI
><P
><TT
CLASS="VARNAME"
>-DMODULE</TT
>: 该选项高速头文件去使用正确的内核模块的定义。</P
></LI
></UL
><P
>我们使用gcc的 <TT
CLASS="OPTION"
>-isystem</TT
> 选项而不是 <TT
CLASS="OPTION"
>-I</TT
> 选项因为要使gcc省略"unused variable"警告当同时打开 <TT
CLASS="OPTION"
>-W -Wall</TT
> 选项和包含时 <TT
CLASS="FILENAME"
>module.h</TT
>头文件时。
在gcc-3.0使用选项 <TT
CLASS="OPTION"
>-isystem</TT
> 会让编译器特殊对待内核头文件,所以会省略"unused variable"警告。如果你使用 <TT
CLASS="OPTION"
>-I</TT
> 选项(或在 gcc 2.9x使用 <TT
CLASS="OPTION"
>-isystem</TT
> 选项时), 将会输出"unused variable"
警告。只管忽略就行了。</P
><P
>再来看一个简单的用来编译模块 <TT
CLASS="FILENAME"
>hello-1.c</TT
>的Makefile:</P
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN242"
></A
><P
><B
>Example 2-2. 用来编译一个基本的模块的Makefile</B
></P
><TABLE
BORDER="1"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><FONT
COLOR="#000000"
><PRE
CLASS="SCREEN"
>TARGET := hello-1
WARN := -W -Wall -Wstrict-prototypes -Wmissing-prototypes
INCLUDE := -isystem /lib/modules/`uname -r`/build/include
CFLAGS := -O2 -DMODULE -D__KERNEL__ ${WARN} ${INCLUDE}
CC := gcc-3.0
${TARGET}.o: ${TARGET}.c
.PHONY: clean
clean:
rm -rf {TARGET}.o</PRE
></FONT
></TD
></TR
></TABLE
></DIV
><P
>作为留给读者的一个练习,编译你的 <TT
CLASS="FILENAME"
>hello-1.c</TT
> 并且使用命令 <B
CLASS="COMMAND"
>insmod
./hello-1.o</B
> 加载入内核。(忽略任何关于污染内核的信息,我们将不久讨论相关内容)。
顺利吗?所有加载入内核的模块都会在文件 <TT
CLASS="FILENAME"
>/proc/modules</TT
>列出。去那看看你的模块是否真的是内核的一部分了。
祝贺你!你现在已经是内核模块的作者了。当你的新鲜劲过去后,使用命令 <B
CLASS="COMMAND"
>rmmod hello-1</B
>卸载模块。再看一下
<TT
CLASS="FILENAME"
>/var/log/messages</TT
> 文件的内容是否有相关的日志内容。</P
><P
>这儿是另一个练习。看到了在声明
<TT
CLASS="FUNCTION"
>init_module()</TT
>上的注释吗? 改变返回值非零,重新编译再加载,发生了什么?</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="x145.html"
ACCESSKEY="P"
>返回</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>返回首页</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="hello2.html"
ACCESSKEY="N"
>继续</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Hello, World (part 1): 最简单的内核模块</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="c143.html"
ACCESSKEY="U"
>回到本章开始</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Hello World (part 2)</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -