linux裝置驅動編寫基礎

beachboyy發表於2014-09-01

Linux裝置驅動編寫基礎

一、linux中的驅動是以模組的形式存在的,這樣就大大提高了驅動的靈活性,linux核心模組的程式結構如下:

l  模組載入函式(必須):module_init()

l  模組解除安裝函式(必須):module_exit()

l  模組許可證宣告(必須):MODULE_LECENSE(“GPL”)

l  模組引數(可選):module_param(a,int,0400)

l  模組到處符號(可選):EXPORT_SYMBOL_GPL(func)

l  模組作者宣告等其他資訊(可選):MODULE_AUTHOR(“name”);

對於模組引數需要使用下面方式進行操作:

         module_patam(a,int,04000);

         MODULE_PARAM_DESC(a,”description”);

        #insmod  module.ko a=100

匯出符號的作用:例如一個模組mod1中定義一個函式func1;在另外一個模組mod2中定義一個函式func2,func2呼叫func1。

在模組mod1中,EXPORT_SYMBOL(func1);

在模組mod2中,extern intfunc1();

就可以在mod2中呼叫func1了。

一個例子:

#include<linux/module.h>

#include<linux/moduleparam.h>

#include<linux/kernel.h>

#include<linux/init.h>

#include<linux/stat.h>

 

#defineDRIVER_AUTHOR "Foobar"

#define DRIVER_DESC   "A sample driver"

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR(DRIVER_AUTHOR);

MODULE_DESCRIPTION(DRIVER_DESC);

MODULE_SUPPORTED_DEVICE("TestDevice");

 

static short intmyshort = 1;

static int myint= 420;

static long intmylong = 9999;

static char*mystring = "blah";

static intarray[2]= {-1, -1};

static intarr_argc = 0;

 

module_param(myshort, short, 0400);

MODULE_PARM_DESC(myshort, "A short integer");

 

module_param(myint, int, 0400);

MODULE_PARM_DESC(myint, "An integer");

 

module_param (mylong,long, 0000);

MODULE_PARM_DESC(mylong, "A long integer");

 

module_param(mystring, charp, 0000);

MODULE_PARM_DESC(mystring, "A character string");

 

module_param_array(array, int, &arr_argc, 0000);

//module_param_array(array, int, arr_argc, 0000); //for kernel<2.6.10

MODULE_PARM_DESC(array, "An array of integers");

 

static int__init hello_2_init (void)

{

         int i;

 

         printk (KERN_INFO "myshort is ashort integer: %hd\n", myshort);

         printk (KERN_INFO "myint is aninteger: %d\n", myint);

         printk (KERN_INFO "mylong is along integer: %ld\n", mylong);

         printk (KERN_INFO "mystring is astring: %s\n\n", mystring);

 

         for (i=0; i<arr_argc; i++)

                   printk (KERN_INFO"array[%d] = %d\n",i, array[i]);

         printk (KERN_INFO "Got %darguments in array\n", arr_argc);

 

         return 0;

}

 

static void__exit hello_2_exit (void)

{

         printk (KERN_INFO "hello drivercleaned up\n");

}

 

module_init(hello_2_init);

module_exit(hello_2_exit);

二、驅動模組的編譯

編譯需注意:核心原始碼路徑必須是配置好的切編譯過的

ifeq($(KERNELRELEASE),)

#KERNELDIR ?=/home/lht/kernel2.6/linux-2.6.14

KERNELDIR ?=/lib/modules/$(shell uname -r)/build

PWD := $(shellpwd)

modules:

         $(MAKE)-C $(KERNELDIR) M=$(PWD) modules

modules_install:

         $(MAKE)-C $(KERNELDIR) M=$(PWD) modules_install

clean:

                  rm -rf *.o *~ core .depend .*.cmd *.ko*.mod.c .tmp_versions modules* Module*

.PHONY:modules modules_install clean

else

   obj-m := hello.o

endif

 

相關文章