新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > Linux驱动总结3

Linux驱动总结3

作者: 时间:2016-12-01 来源:网络 收藏
3、确定一个具体的条件,比如数据有无,具体的条件根据实际的情况设计。
/*等待条件*/
static bool havedata = false;
4、在需要堵塞的读函数,写函数中分别实现堵塞,首先定义等待队列的节点,并添加到队列中去,然后等待事件的唤醒进程。但是由于读写操作的两个等待队列都是基于条件havedata的,所以在读完成以后需要唤醒写,写完成以后需要唤醒读操作,同时更新条件havedata,最后还要移除添加的等待队列节点。
/*read函数的实现*/
static ssize_t mem_read(struct file *filp,char __user *buf, size_t size,loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct mem_dev *dev = filp->private_data;
/*参数的检查,首先判断文件位置*/
if(p >= MEMDEV_SIZE)
return 0;
/*改正文件大小*/
if(count > MEMDEV_SIZE - p)
count = MEMDEV_SIZE - p;
#if 0
/*添加一个等待队列节点到当前进程中*/
DECLARE_WAITQUEUE(wait_r,current);
/*将节点添加到等待队列中*/
add_wait_queue(&dev->rdqueue,&wait_r);
/*添加等待队列,本来采用if即可,但是由于信号等可能导致等待队列的唤醒,因此采用循环,确保不会出现误判*/
#endif
while(!havedata)
{
/*判断用户是否设置为非堵塞模式读,告诉用户再读*/
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
/*依据条件havedata判断队列的状态,防止进程被信号唤醒*/
wait_event_interruptible(dev->rdqueue,havedata);
}
spin_lock(&dev->lock);
/*从内核读数据到用户空间,实质就通过private_data访问设备*/
if(copy_to_user(buf,(void *)(dev->data p),count))
{
/*出错误*/
ret = -EFAULT;
}
else
{
/*移动当前文件光标的位置*/
*ppos = count;
ret = count;
printk(KERN_INFO "read %d bytes(s) from %d",count,p);
}
spin_unlock(&dev->lock);
#if 0
/*将等待队列节点从读等待队列中移除*/
remove_wait_queue(&dev->rdqueue,&wait_r);
#endif
/*更新条件havedate*/
havedata = false;
/*唤醒写等待队列*/
wake_up_interruptible(&dev->wrqueue);
return ret;
}
/*write函数的实现*/
static ssize_t mem_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
/*获得设备结构体的指针*/
struct mem_dev *dev = filp->private_data;
/*检查参数的长度*/
if(p >= MEMDEV_SIZE)
return 0;
if(count > MEMDEV_SIZE - p)
count = MEMDEV_SIZE - p;
#if 0
/*定义并初始化一个等待队列节点,添加到当前进程中*/
DECLARE_WAITQUEUE(wait_w,current);
/*将等待队列节点添加到等待队列中*/
add_wait_queue(&dev->wrqueue,&wait_w);
#endif
/*添加写堵塞判断*/
/*为何采用循环是为了防止信号等其他原因导致唤醒*/
while(havedata)
{
/*如果是以非堵塞方式*/
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
/*分析源码发现,wait_event_interruptible 中存在DECLARE_WAITQUEUE和add_wait_queue的操作,因此不需要手动添加等待队列节点*/
wait_event_interruptible(&dev->wrqueue,(!havedata));
}
spin_lock(&dev->lock);
if(copy_from_user(dev->data p,buf,count))
ret = -EFAULT;
else
{
/*改变文件位置*/
*ppos = count;
ret = count;
printk(KERN_INFO "writted %d bytes(s) from %d",count,p);
}
spin_unlock(&dev->lock);
#if 0
/*将该等待节点移除*/
remove_wait_queue(&dev->wrqueue,&wait_w);
#endif
/*更新条件*/
havedata = true;
/*唤醒读等待队列*/
wake_up_interruptible(&dev->rdqueue);
return ret;
}
5、应用程序采用两个不同的进程分别进行读、写,然后检测顺序是否可以调换,检查等待是否正常。
上一页 1 2 3 下一页

关键词: Linux驱动总

评论


技术专区

关闭