驱动程序的基本框架

 头文件
    就像你写C程序需要包含C库的头文件那样,Linux内核编程也需要包含Kernel头文件,大多的Linux驱动程序需要包含下面三个头文件:

   

 #include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

 

    init.h 定义了驱动的初始化和退出相关的函数,
    kernel.h 定义了经常用到的函数原型及宏定义
    module.h 定义了内核模块相关的函数、变量及宏。
    初始化
    任何一个驱动都去需要提供一个初始化函数,当驱动加载到内核中时,这个初始化函数就会被自动执行,初始化的函数原型定义如下:

   

 typedef int (*initcall_t)(void);

 

    驱动程序是通过module_init宏来声明初始化函数的:

   

 static int __init hello_init(void)
{
    printk(KERN_ALERT "Hello World!\n");
    return 0;
}
module_init(hello_init);

 

    __init 宏告诉编译器如果这个模块被编译到内核则把这个函数放到(.init.text)段,这样当函数初始化完成后这个区域可以被清除掉以节约系统内存。Kenrel启动时看到的消息“Freeing unused kernel memory: xxxk freed”同它有关。
    初始化函数是有返回值的,只有在初始化成功是才返回0,否则返回错误码(errno)。


    卸载
    如果驱动程序编译成模块(动态加载)模式,那么它需要一个清理函数。当移除一个内核模块时这个函数被调用执行清理工作。清理函数的函数原型定义为:

   

 typedef void (*exitcall_t)(void);

 

    驱动程序是通过module_exit宏来声明清理函数的:

 

 static void __exit hello_exit(void)
{
    printk(KERN_ALERT "Goodbye World!\n");
}
module_exit(hello_exit);

 

    同__init类似,如果驱动被编译进内核,则__exit宏会忽略清理函数,因为编译进内核的模块不需要做清理工作。显然,__init和__exit对动态加载的模块是无效的。


    版权信息
    Linux内核是按照GPL发布的,同样Linux的驱动程序也要提供版权信息,否则当加载到内核中是系统会给出警告信息。Hello World例子中的版权信息是GPL。

 

 MODULE_LICENSE("GPL");

 

    后续
    这里你了解了一个驱动程序的基本框架,所有的驱动都会包含这些内容。

posted @ 2014-10-18 15:33  小天儿  阅读(631)  评论(0)    收藏  举报