Linux设备驱动编程之结构化设备驱动程序
来源:互联网 发布:mvc 网站源码 响应式 编辑:程序博客网 时间:2024/05/16 05:35
阅读本文请首先阅读:《Linux设备驱动编程之内存与I/O操作》
在1~9节关于设备驱动的例子中,我们没有考虑设备驱动程序的结构组织问题。实际上,Linux设备驱动的开发者习惯于一套约定俗成的数据结构组织方法和程序框架。
设备结构体
Linux设备驱动程序的编写者喜欢把与某设备相关的所有内容定义为一个设备结构体,其中包括设备驱动涉及的硬件资源、全局软件资源、控制(自旋锁、互斥锁、等待队列、定时器等),在涉及设备的操作时,仅仅操作这个结构体就可以了。
对于"globalvar"设备,这个结构体就是:
struct globalvar_dev
{
int global_var = 0;
struct semaphore sem;
wait_queue_head_t outq;
int flag = 0;
};
open()和release()
一般来说,较规范的open( )通常需要完成下列工作:
1. 检查设备相关错误,如设备尚未准备好等;
2. 如果是第一次打开,则初始化硬件设备;
3. 识别次设备号,如果有必要则更新读写操作的当前位置指针f_ops;
4. 分配和填写要放在file->private_data里的数据结构;
5. 使用计数增1。
release( )的作用正好与open( )相反,通常要完成下列工作:
1. 使用计数减1;
2. 释放在file->private_data中分配的内存;
3. 如果使用计算为0,则关闭设备。
我们使用LDD2中scull_u的例子:
int scull_u_open(struct inode *inode, struct file *filp)
{
Scull_Dev *dev = &scull_u_device; /* device information */
int num = NUM(inode->i_rdev);
if (!filp->private_data && num > 0)
return -ENODEV; /* not devfs: allow 1 device only */
spin_lock(&scull_u_lock);
if (scull_u_count && (scull_u_owner != current->uid) && /* allow user */
(scull_u_owner != current->euid) && /* allow whoever did su */
!capable(CAP_DAC_OVERRIDE)) {
/* still allow root */
spin_unlock(&scull_u_lock);
return -EBUSY; /* -EPERM would confuse the user */
}
if (scull_u_count == 0)
scull_u_owner = current->uid; /* grab it */
scull_u_count++;
spin_unlock(&scull_u_lock);
/* then, everything else is copied from the bare scull device */
if ( (filp->f_flags & O_ACCMODE) == O_WRONLY)
scull_trim(dev);
if (!filp->private_data)
filp->private_data = dev;
MOD_INC_USE_COUNT;
return 0; /* success */
}
int scull_u_release(struct inode *inode, struct file *filp)
{
scull_u_count--; /* nothing else */
MOD_DEC_USE_COUNT;
return 0;
}
在1~9节关于设备驱动的例子中,我们没有考虑设备驱动程序的结构组织问题。实际上,Linux设备驱动的开发者习惯于一套约定俗成的数据结构组织方法和程序框架。
设备结构体
Linux设备驱动程序的编写者喜欢把与某设备相关的所有内容定义为一个设备结构体,其中包括设备驱动涉及的硬件资源、全局软件资源、控制(自旋锁、互斥锁、等待队列、定时器等),在涉及设备的操作时,仅仅操作这个结构体就可以了。
对于"globalvar"设备,这个结构体就是:
struct globalvar_dev
{
int global_var = 0;
struct semaphore sem;
wait_queue_head_t outq;
int flag = 0;
};
open()和release()
一般来说,较规范的open( )通常需要完成下列工作:
1. 检查设备相关错误,如设备尚未准备好等;
2. 如果是第一次打开,则初始化硬件设备;
3. 识别次设备号,如果有必要则更新读写操作的当前位置指针f_ops;
4. 分配和填写要放在file->private_data里的数据结构;
5. 使用计数增1。
release( )的作用正好与open( )相反,通常要完成下列工作:
1. 使用计数减1;
2. 释放在file->private_data中分配的内存;
3. 如果使用计算为0,则关闭设备。
我们使用LDD2中scull_u的例子:
int scull_u_open(struct inode *inode, struct file *filp)
{
Scull_Dev *dev = &scull_u_device; /* device information */
int num = NUM(inode->i_rdev);
if (!filp->private_data && num > 0)
return -ENODEV; /* not devfs: allow 1 device only */
spin_lock(&scull_u_lock);
if (scull_u_count && (scull_u_owner != current->uid) && /* allow user */
(scull_u_owner != current->euid) && /* allow whoever did su */
!capable(CAP_DAC_OVERRIDE)) {
/* still allow root */
spin_unlock(&scull_u_lock);
return -EBUSY; /* -EPERM would confuse the user */
}
if (scull_u_count == 0)
scull_u_owner = current->uid; /* grab it */
scull_u_count++;
spin_unlock(&scull_u_lock);
/* then, everything else is copied from the bare scull device */
if ( (filp->f_flags & O_ACCMODE) == O_WRONLY)
scull_trim(dev);
if (!filp->private_data)
filp->private_data = dev;
MOD_INC_USE_COUNT;
return 0; /* success */
}
int scull_u_release(struct inode *inode, struct file *filp)
{
scull_u_count--; /* nothing else */
MOD_DEC_USE_COUNT;
return 0;
}
上面所述为一般意义上的设计规范,应该说是option(可选的)而非强制的。
作者: 宋宝华 出处: 天极开发
- Linux设备驱动编程之结构化设备驱动程序
- 深入浅出Linux设备驱动编程--结构化设备驱动程序
- linux-设备驱动之device设备结构
- linux设备驱动之 i2c设备驱动 at24c08驱动程序分析
- 深入浅出Linux设备驱动编程--字符设备驱动程序
- Linux设备驱动程序——设备驱动编程基础
- Linux设备驱动程序——字符设备驱动编程
- 浅谈linux驱动之-字符设备驱动程序
- Linux设备驱动之USB网卡驱动程序
- 深入浅出Linux设备驱动之字符设备驱动程序
- 深入浅出Linux设备驱动之字符设备驱动程序
- Linux设备驱动之字符设备驱动程序转
- 深入浅出Linux设备驱动之字符设备驱动程序
- 深入浅出Linux设备驱动之字符设备驱动程序
- 深入浅出Linux设备驱动之字符设备驱动程序
- linux设备驱动程序之简单字符设备驱动
- 深入浅出Linux设备驱动之字符设备驱动程序
- linux设备驱动程序之简单字符设备驱动
- SQLServer2000数据库文件损坏时如何恢复
- synchronized用法
- Linux设备驱动编程之内存与I/O操作
- 第三方发布工具及剪影暂时无法使用的原因说明
- appfuse2.0 to maven
- Linux设备驱动编程之结构化设备驱动程序
- 来段后门,反弹的,高手略过哈(转自http://forum.darkst.com/read.php?tid=9537)
- 自定义TabControl控件
- Linux设备驱动编程之复杂设备驱动
- [转]WPF简介
- 李阳疯狂英语突破对话(29)-欢迎到李阳疯狂英语公司来
- 数据库操作函数类的源代码
- [转]Silverlight入门(部分)
- 九月最值得收藏的IT内容回顾