这是一个简单而完整的实例,对于理解Linux下的驱动模块是非常有帮助的。
1.源码如下:
/*
* hello.c -- the example of printf "hello world!" in the screen of driver program
*/
#include <linux/init.h>
#include <linux/mole.h>
MODULE_LICENSE("Dual BSD/GPL");/* declare the license of the mole ,it is necessary */
static int hello_init(void)
{
printk(KERN_ALERT "Hello World enter!\n");
return 0;
}
static int hello_exit(void)
{
printk(KERN_ALERT "Hello world exit!\n");
}
mole_init(hello_init); /* load the mole */
mole_exit(hello_exit); /* unload the mole */
进入目录:
[root@Alex_linux /]#cd /work/jiakun_test/moletest
[root@Alex_linux moletest]# vi hello.c
然后拷入上面书上的源码。
2.编译代码:
1>.首先我在2.4内核的虚拟机上进行编译,编译过程如下:
[root@Alex_linux moletest]#gcc -D__KERNEL__ -I /usr/src/linux -DMODULE -Wall -O2 -c -o hello.o hello.c
其中-I选项指定内河源码,也就是内核源码树路径。编译结果:
hello.c:1:22: net/sock.h: No such file or directory
hello.c: In function `hello_init':
hello.c:6: warning: implicit declaration of function `printk'
hello.c:6: `KERN_ALERT' undeclared (first use in this function)
hello.c:6: (Each undeclared identifier is reported only once
hello.c:6: for each function it appears in.)
hello.c:6: parse error before string constant
hello.c: In function `hello_exit':
hello.c:11: `KERN_ALERT' undeclared (first use in this function)
hello.c:11: parse error before string constant
hello.c: At top level:
hello.c:13: warning: type defaults to `int' in declaration of `mole_init'
hello.c:13: warning: parameter names (without types) in function declaration
hello.c:13: warning: data definition has no type or storage class
hello.c:14: warning: type defaults to `int' in declaration of `mole_exit'
hello.c:14: warning: parameter names (without types) in function declaration
hello.c:14: warning: data definition has no type or storage class
在网上查询有网友提示没有引入kernel.h
解决:vi hello.c
在第一行加入:#include <linux/kernel.h>
再次编译仍然报KERN_ALERT没有声明
修改编译条件-I,再次编译:
[root@Alex_linux moletest]#gcc -D__KERNEL__ -I /usr/src/linux -DMODULE -Wall -O2 -c -o hello.o hello.c
[root@Alex_linux moletest]#ls
hello.c hello.o Makefile
[root@Alex_linux moletest]#
2>.接着我尝试在2.6内核的虚拟机上进行编译
编译过程如下:
[root@JiaKun moletest]# ls
hello.c makefile
[root@JiaKun moletest]# vi hello.c
[root@JiaKun moletest]# make
make -C /mylinux/kernel/2.4.18-rmk7 M=/home/alex/test/moletest moles
make: *** /mylinux/kernel/2.4.18-rmk7: No such file or directory. Stop.
make: *** [moles] Error 2
[root@JiaKun moletest]# vi makefile
[root@JiaKun moletest]# make
make -C /usr/src/kernels/2.6.18-53.el5-i686 M=/home/alex/test/moletest moles
make[1]: Entering directory `/usr/src/kernels/2.6.18-53.el5-i686'
scripts/Makefile.build:17: /home/alex/test/moletest/Makefile: No such file or directory
make[2]: *** No rule to make target `/home/alex/test/moletest/Makefile'. Stop.
make[1]: *** [_mole_/home/alex/test/moletest] Error 2
make[1]: Leaving directory `/usr/src/kernels/2.6.18-53.el5-i686'
make: *** [moles] Error 2
[root@JiaKun moletest]# mv makefile Makefile
[root@JiaKun moletest]# make
make -C /usr/src/kernels/2.6.18-53.el5-i686 M=/home/alex/test/moletest moles
make[1]: Entering directory `/usr/src/kernels/2.6.18-53.el5-i686'
CC [M] /home/alex/test/moletest/hello.o
Building moles, stage 2.
MODPOST
CC /home/alex/test/moletest/hello.mod.o
LD [M] /home/alex/test/moletest/hello.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.18-53.el5-i686'
[root@JiaKun moletest]# ls
hello.c hello.ko hello.mod.c hello.mod.o hello.o Makefile Mole.symvers
3.执行代码,加载驱动模块:
2.4内核加载模块:
insmod ./hello.o
但是此时并没有输出printk打印的信息。但是可以在/var/log/messages 中看到打印的信息,这是由于KERN_ALERT优先级不够高。这里
需要修改为:KERN_EMERG。再次编译,加载模块即可以看到结果
2.6内核加载模块:
[root@JiaKun moletest]# insmod hello.ko
[root@JiaKun moletest]#
Message from syslogd@ at Sat Jul 26 19:52:44 2008 ...
JiaKun kernel: Hello, world
有的朋友可能会出现insmod命令找不到的错误,这可能有下面几个原因:
<1> 你的系统没有安装mole-init-tools工具,关于此问题,只需安装即可,但是一般装完系统是有这个命令的。
<2> 环境变量没有添加导致不能使用该命令。使用echo $PATH即可查看PATH环境变量,发现没有/sbin这个路径,所以你当然不能使用insmod这个命令了。解决的方法很简单,只需在命令行输入:
PATH = "$PATH:/sbin"即可添加。(insmod在/sbin这个目录下,你可以使用whereis insmod查看)。
<3> insmod这个命令需要在root权限下才能使用。
加载完成后你可以输入lsmod查看hello这个模块哦。
4.卸载驱动模块:rmmod hello.
加载模块后就可在屏幕上看到如下信息:Hello world enter.
卸载时就可在屏幕上看到如下信息:hello world exit.
[root@JiaKun moletest]# rmmod hello.ko
[root@JiaKun moletest]#
Message from syslogd@ at Sat Jul 26 19:52:58 2008 ...
JiaKun kernel: Goodbye, cruel world
另外,如果有多个文件,则按下列方式编写Makefile文件(file1.c、file2.c):
obj -m := molename.o
mole-objs := file1.o file2.o
Ⅱ 如何编译驱动程序
驱动的编译和上层应用程序的编译完全不同,作为初学者应该先了解一下,即使你还不懂得怎么写驱动程序。
首先安装DDK,然后随便找一个例子来测试。在菜单中找到BUILD环境菜单执行,不同的系统要使用不同的BUILD环境。会打开一个DOS窗口,这时CD到那个例子程序,输入 build –cZ回车就可以了。 驱动程序都是用一个由DDK提供的叫build.exe的工具编译的。此程序以一个名为SOURCES的文件作为输入,该文件中包含目标可执行文件的名称、类型和要创建的可执行文件的路径,注意这个文件没有后缀名。
SOURCES的文件格式:
TARGETNAME=drivername ,
- 本参数用于指定生成的设备驱动程序名称(不需后缀名),所产生的文件
- 为drivername.sys.
TARGETPATH=./lib
- 本参数用于指定生成的设备驱动程序所存放的路径. 一般采用./lib.
TARGETTYPE=DRIVER
- build能够生成许多不同的目标对象,设备驱动程序一般选用 DRIVER.
INCLUDES=path1;path2;...
- 本参数是可选的, 用于指定其他的#include文件的搜索路径.
TARGETLIBS=lib1;lib2;...
- 本参数是可选的, 用于指定其他的lib库文件的搜索路径.
SOURCES=file1.c file2.c ...
- 本参数用于指定需被编译的全部源文件名称, 后缀名不能省略,文件名之间用空格分开.
SOURCES文件是必需的,如果没有它则表示没有任何源文件需要编译。
如果要换行可以用 ‘/’ 符号,表示对上一行的继续。
也可以创建DIRS文件,DIRS文件用于指定在当前目录下必须创建的子目录。
DIRS文件格式:
DIRS文件的内容由一系列用空格分开的目录名组成
DIRS = /
subdir1 /
subdir2 /
subdir3
DIRS文件是可选的。
有的时候,会提示找不到依赖的文件(.h,.lib 之类),其实设置好 source 文件的
INCLUDES和TARGETLIBS就可以,我第一次编译时就碰到这个问题,和VC环境区别较大,但习惯就好。
Ⅲ vs2010如何编译驱动
1、安装VS2010,安装WDK 7.0(DDK);
2、新建VC++->Empty Project
3、打开Configuration Manager 并新建一个名称为“ dirver ”的Solution Configuration 并将“dirver” 设为Active Solution Configuration .
4、打开View-> property Manager。
5、在"dirver" solution configuration 上点击右键,选择Add new property Sheet。取名为“dirverProperty”. 并对他进下以下设置。
5.1. C\C++ - General - Debug Information Format = Program Database (/Zi)
5.2. C\C++ - Preprocessor - Preprocessor Definitions = _X86_ [add also DBG for Debug config]
【WIN32;_DEBUG;_X86_;i386;STD_CALL;CONDITION_HANDLING;WIN32_LEAN_AND_MEAN;NT_UP;SRVDBG;DBG;_IDWBUILD;_WIN32_WINNT=0x0400;% (PreprocessorDefinitions)】
5.3. C\C++ - Code Generation - Enable C++ Exceptions = No
5.4. C\C++ - Code Generation - Basic Runtime Checks = Default
5.5. C\C++ - Code Generation - Buffer Security Check = No (/GS-)
5.6. C\C++ - Advanced - Calling Convention = __stdcall (/Gz)
5.7. C\C++ - Advanced - Compile As = Compile as C Code (/TC) [if you are going to use plain C]
5.8. Linker - General - Output File = $(OutDir)\$(ProjectName).sys
5.9. Linker - General - Enable Incremental Linking = Default
5.10. Linker - Input - Additional Dependencies = ntoskrnl.lib hal.lib $(NOINHERIT) [add here needed libs here e.g. ntoskrnl.lib hal.lib]
【不知道上面是不是笔误,应该为:ntoskrnl.lib;hal.lib;%(AdditionalDependencies)】
5.11. Linker - Input - Ignore All Default Libraries = Yes (/NODEFAULTLIB)
5.12. Linker - Manifest File - Generate Manifest = No
5.13. Linker - System - SubSystem = Native (/SUBSYSTEM:NATIVE)
5.14. Linker - System - Driver = Driver (/DRIVER)
5.15. Linker - Advanced - Entry Point = DriverEntry
5.16. Linker - Advanced - Base Address = 0x10000
5.17. Linker - Advanced - Randomized Base Address = Disable (/DYNAMICBASE:NO)
【这个也是错误的:应该置空】
5.18. Linker - Advanced - Data Execution Prevention (DEP) = Disable (/NXCOMPAT:NO)
【这个也是错误的:应该置空】
6. Config VC++ Directories
6.1 Open Open up property manager by clicking on Menu View->Property Manager.
6.2 Expand the project node and then the Configuration|Platform nodes, you will see "Microsoft.cpp.<Platform>.users" file for each Configuration|Platform. These are the files
for the global settings, similar to the old tools/Options/VC++ Directories.
6.3 Multi-Select "Microsoft.cpp.<Platform>.users", right click and bring up the property page window
6.4 In the property page window, click on "VC++ Directories" (for example) in the left pane, add new paths for the directories such as "Include Directories". separated by
semicolons
(eg:Include Directories config As:
$(ddkroot)\INC
$(ddkroot)\INC\WNET
$(ddkroot)\INC\DDK\WNET
Library Directories config As:
$(ddkroot)\LIB\WNET\I386
)
6.5 Make sure to save the settings before shutting down Visual Studio.
6.6 Re-launch Visual Studio and the new settings will be in effect.
6.7 Note: If you would like to only change the settings for one project, you can right click on the project and bring up the property page. Change the settings for “VC++
Directories”, these settings will be persisted to the project file.
七. OK. Have done. Now you can test it with simple code, e.g.:
#include "ntddk.h"
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
return STATUS_UNSUCCESSFUL;
}
特别说明:
1.
Visual Studio 2010 在智能设备开发方面只支持Windows Phone OS 7.0。如果你要为Windows CE 5.0和Windows Mobile 6.5开发应用程序,请安装Visual Studio 2008。
2.
做驱动开发时,SDK的版本要和WDK的版本一致,即Win7 WDK要配Win7 SDK,否则会出现编译错误。VS2010里集成了Windows SDK 7.0A。
3.
如果出现类似如下编译错误,解决方法是:拷贝C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\sal.h,然后覆盖掉C:\WinDDK\7600.16385.1\inc\api\sal.h。
C:\Program Files\Microsoft Visual Studio 10.0\VC\include\crtdefs.h(550): error C2143: syntax error : missing ')' before 'const'
C:\Program Files\Microsoft Visual Studio 10.0\VC\include\crtdefs.h(550): error C2143: syntax error : missing '{' before 'const'
.......
Ⅳ 修改了WINCE自带的驱动程序后如何编译
IDE 方式的编译很简单,以PB5.0为例,打开定制内核的工程,在左边的workspaceFileView中找到你已经修改了的目录,然后单击右键弹出菜单,在菜单中选择Build and Sysgen Current Project,这样PB就会编译指定的目录中的项目源码文件,然后执行sysgen命令根据source文件中的内容生成目标文件并复制到当前内核工程目录下。 命令行方式的编译需要打开Build OS Open Release Directory,以cd命令进入你已经修改的驱动程序目录中,然后键入build –cfs,然后键入 sysgen –p 项目名称,一般项目名称为source文件中的TARGETNAME。