字符设备驱动程序的设计
2016-01-22 17:27
190 查看
【字符设备驱动程序的组成】
字符设备驱动程序包含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_ops的file_operation结构体变量,的部分成员并对其中用XXX_write、XXX_read、XXX_ioctl、XXXX_open、XXX_release进行初始化。XXX_write、XXX_read、XXX_ioctl、XXXX_open、XXX_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);
【字符设备驱动程序的接口函数】
read()函数
read()函数从设备端口读取数据,并将这些数据从内核空间复制到用户空间,其示例代码如下:
staticssize_t
XXX_read(struct file *filp,char*buffer,size_t count,loff_t
*ppos)
{
//从设备读取数据
//从内核空间复制到用户空间
//返回读取的字节数
};
write()函数
write()函数从用户空间接收数据,将这些数据复制到内核空间,然后进一步写到设备端口,其示例代码如下:
staticssize_t XXX_write( struct file *filp,const char *buffer,size_t count)
{
//从用户空间复制数据到内核空间
//写数据到设备
//返回写入的字节数
};
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;
}
open()函数
open()函数使用MOD_INC_USE_COUNT宏增加打开驱动程序打开的次数,以防止还有设备打开时卸载驱动程序,如果没有在加载函数中进行设备的初始化,而且是第一次打开设备,则需要进行设备的初始化,其示例代码如下:
staticint XXX_open(struct inode *inode,struct file *file)
{
MOD_INC_USE_COUNT;
//如果是初次打开该设备,则对设备进行初始化
//驱动使用计数器加1
return0;
};
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_COUNT和MOD_INC_USE_COUNT必须成对出现。
字符设备驱动程序包含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_ops的file_operation结构体变量,的部分成员并对其中用XXX_write、XXX_read、XXX_ioctl、XXXX_open、XXX_release进行初始化。XXX_write、XXX_read、XXX_ioctl、XXXX_open、XXX_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);
【字符设备驱动程序的接口函数】
read()函数
read()函数从设备端口读取数据,并将这些数据从内核空间复制到用户空间,其示例代码如下:
staticssize_t
XXX_read(struct file *filp,char*buffer,size_t count,loff_t
*ppos)
{
//从设备读取数据
//从内核空间复制到用户空间
//返回读取的字节数
};
write()函数
write()函数从用户空间接收数据,将这些数据复制到内核空间,然后进一步写到设备端口,其示例代码如下:
staticssize_t XXX_write( struct file *filp,const char *buffer,size_t count)
{
//从用户空间复制数据到内核空间
//写数据到设备
//返回写入的字节数
};
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;
}
open()函数
open()函数使用MOD_INC_USE_COUNT宏增加打开驱动程序打开的次数,以防止还有设备打开时卸载驱动程序,如果没有在加载函数中进行设备的初始化,而且是第一次打开设备,则需要进行设备的初始化,其示例代码如下:
staticint XXX_open(struct inode *inode,struct file *file)
{
MOD_INC_USE_COUNT;
//如果是初次打开该设备,则对设备进行初始化
//驱动使用计数器加1
return0;
};
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_COUNT和MOD_INC_USE_COUNT必须成对出现。
相关文章推荐
- (安全系列一)Android Apk反编译得到Java源代码
- 解决有java命令,没有javac命令
- 数据结构-单链表的java实现
- Matlab—Matlab操作mysql数据库
- 正向代理 & 反向代理
- 玩转swift(二)
- JSP SHELL有关的whoami漏洞
- hud-2821-Pusher
- Myeclipse10下搭建SSH框架(图解)Struts2.1+Spring3.0+Hibernate3.3
- 费伯纳西数列(Fibonacci)的输出
- 常用的二种修改mysql最大连接数的方法
- oschina的android源码分析学习-MainActivity
- Linux与JVM的内存关系分析
- 图的基础算法-广度优先搜索/深度优先搜索
- leetcode 322. Coin Change
- Cursor类的一个例子
- Red Hat 7 vncserver配置与问题
- Python中正则表达式的使用
- 读取含中文字符的txt文档python代码
- Java URI 中的 getSchemeSpecificPart() 方法