字符设备驱动程序的设计

【字符设备驱动程序的组成】

     字符设备驱动程序包含5个部分:头文件、file_operation结构体变量、接口函数、加载函数以及卸载函数。

 头文件的部分包含进数据结构以及内核函数要用到的头文件。file_operation结构体变量部分定义file_operation结构体的变量,该结构体声明了驱动程序所有的接口函数。接口函数部分包含字符驱动设备驱动程序与内核应用程序交互的read()函数、write()函数、open()函数、ioctl()函数、relase()函数。加载函数用于加载驱动程序至内核,卸载函数用于从内核卸载驱动程序。

 

file_operation结构体变量】

用户进程利用系统调用在对设备文件进行诸如read()write()等操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取file_operation结构体变量相应的函数指针,接着把控制权交给该函数。一个字符设备驱动设备即是file_operation结构体的一个变量。、,字符设备驱动程序中应该首先定义该结构体的变量,定义该结构体的方法如下:

 

static struct file_operation XXX_fops={

   owner:  THIS_MODULE,

   write:   XXX_write,

   read:    XXX_read;

  ioctl:    XXX_ioctl;

  open   XXXX_open,

  release:     XXX_release,

};

 

以上定义了名为XXX_opsfile_operation结构体变量,的部分成员并对其中用XXX_writeXXX_readXXX_ioctlXXXX_openXXX_release进行初始化。XXX_writeXXX_readXXX_ioctlXXXX_openXXX_release函数分别对应XXX_ops的一个接口函数,他们构成了字符驱动程序的主体。

PS:XXX可以随意指定,一般用设备文件名。

 

【字符设备驱动的加载函数和卸载函数】

加载函数调用驱动注册函数实现驱动程序在内核中的注册,同时还有可能对设备进行初始化,在驱动程序加载时被调用:卸载函数调用解除注册函数实现驱动程序在内核中的解除注册,在驱动程序卸载时被调用。示例代码如下:

 

/*加载函数的示例代码*/

static int _init XXX_init(void)

{

  /*the codefor registing driver*/

  return 0;

}

static void _exit XXX_exit(void)

{

   /*thecode for canseling to regist driver*/

}

 

/*指定加载函数和卸载函数*/

module_init(XXX_init);

module_exit(XXX_exit);

 

 

【字符设备驱动程序的接口函数】

  1. read()函数

    read()函数从设备端口读取数据,并将这些数据从内核空间复制到用户空间,其示例代码如下:

    staticssize_t  XXX_read(struct file *filp,char*buffer,size_t count,loff_t  *ppos)

    {

       //从设备读取数据

       //从内核空间复制到用户空间

       //返回读取的字节数

    }

     

  2. write()函数

    write()函数从用户空间接收数据,将这些数据复制到内核空间,然后进一步写到设备端口,其示例代码如下:

    staticssize_t XXX_write( struct file *filp,const char *buffer,size_t count)

    {

       //从用户空间复制数据到内核空间

       //写数据到设备

       //返回写入的字节数

    }

     

  3. ioctl()函数

    iotcl()函数实现不能由read()write()实现的设备功能,其示例代码如下:

    staticint XXX_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsignedlong arg)

    {

      switch(cmd){

    case 1:

        //命令为1时的处理代码

        Break;

    case 2:

        //命令为2时的处理代码

        Break;

    case 3:

        //错误命令的处理代码

        Break;

    }

    return 0

    }

     

  4. open()函数

    open()函数使用MOD_INC_USE_COUNT宏增加打开驱动程序打开的次数,以防止还有设备打开时卸载驱动程序,如果没有在加载函数中进行设备的初始化,而且是第一次打开设备,则需要进行设备的初始化,其示例代码如下:

    staticint XXX_open(struct inode *inode,struct file *file)

    {

    MOD_INC_USE_COUNT

    //如果是初次打开该设备,则对设备进行初始化

    //驱动使用计数器加1

    return0

    }

     

  5. release()函数

    release()函数使用MOD_DEC_USE_COUNT宏减少驱动程序打开的次数,以防止还有设备打开时卸载驱动程序。其示例代码如下:

    staticint XXX_release(struct inode *inode,struct file *filp)

    {

      MOD_DEC_USE_COUNT;

     //如果设备不再使用,则关闭设备

      //驱动使用计数器减1

     return 0;

    }

     

    MOD_DEC_USE_COUNTMOD_INC_USE_COUNT必须成对出现。

你可能感兴趣的:(学习笔记,字符设备驱动,嵌入式实验)