1、最简单的设备驱动程序hcllo.c
#include
#inelude
MODULE_LICENSE(nGPLH);
static int hello_init(void)
{
printk (KERN_ALERT ,,Hello, Hello, Linux Driver ! \nn);
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT nGoodbye, Hello,Linux Driver ! \nH );
}
module_init(hello_init);
module_exit(hello_exit);
说明:
前两行为所包含的头文件,位于内核源码的目录下include文件夹下的。
程序中的MODULE_LICENSE ( nGPL");用于声明模块的许可证。
⑶module_init()为注册加载时执行的函数,module_exit ()为/注册卸载时执彳亍的函数。传 递给这两个函数的的参数为所要进行初始化的函数的地址(函数名)。
⑷模块的编译:使用gcc编译器,与编译普通程序不同的是要在参数-工后指定内核源代码 的目录,2.4的内核模块编译后将生成.o格式的文件。命令行下的编译格式如下:
gcc -DMODULE -DKERNEL -I /usr/src/linux-2.4.20/include -c hello.c
?其中-DMODULE -D—KERNEL—为两个宏定义,如果文件中包含这两个的宏定义,可以在gCC 编译时不用再指定。文件中宏定义的内容如下:
#ifndef —KERNEL—
#define —KERNEL—
#endif
#ifndef MODULE
#define MODULE
#endif
(5)模块的加载与卸载
模块加载:在命令行下执行:insmod hello.o?如果成功加载到内核将在终端上显水:
Hello, Hello,Linux Driver !。
查看加载的模块:通过lsmod命令町以杳看内核屮已经加载的模块。
模块的卸载:rmmod hello . Oo卸载成功的话将终端显示:Goodbye, Hello, Linux Driver ! ⑹ 驱动模块运行在内核空间,运行时不能依赖于任何函数库和模块连接,所以在耳驱动时 所调用的函数只能是作为内核一部分的函数。内核代码不能实现浮点书运算。
2、-般驱动程序都会实现一个file_operation结构中的函数。如test.c程序中所实现的 file_operation 结构如下:
struct, file_operations test_fops={
read:read_test,
write:writ,
open:open_test,
release:release_test,
};
该驱动程序所实现的功能是在内存中开辟-?段空间,write实现了往这段内屮写数据,read 正好相反,是从这段内存中读出数据。
(1)头文件和全局变量定义如下:
#include
#includedinux/f s . h>
#includevlinux/mm.h>
#inc丄ude
#include
#include
#includedinux/module . h>
#include
#include
//设备号//存放内心空间的指针//当前内存中拥有的数据的字节数
//设备号
//存放内心空间的指针
//当前内存中拥有的数据的字节数
unsigned int test_major = 254; char *str_test;
unsigned int count_driver;
const unsigned int count_driver_max=255;//容虽的最大值
(2)模块初始化函数为:
static int test_init_modu1e(void)
int result;
result = register_chrdev (test_majorz ,,test,,z &test_fops);
if (result < 0)
{
printk (KERN_INFOntest: can 11 get major nuir.ber\nn);
return result;
}
prin tk ("registei: ok\nn );
if ( (str_test= (char*) kmalloc