支持异步通知的globalfifo驱动---Linux设备驱动开发详解

增加异步通知后的globalfifo设备结构体
struct globalfifo_dev {
struct cdev cdev;
unsigned int current_len;
unsigned char mem[GLOBALFIFO_SIZE];
struct mutex mutex;
wait_queue_head_t r_wait;
wait_queue_haea_t w_wait;
struct fasync_struct *async_queue;
}
支持异步通知的globalfifo设备驱动的fasync()函数

static int globalfifo_fasync(int fd, struct file *filp, int mode)
{
struct globalfifo_dev *dev=filp->private_data;
return fasync_helper(fd, filp, mode, &dev->async_queue);
}

**支持异步通知的globalfifo设备驱动写函数**

static ssize_t globalfifo_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
struct globalfifo_dev *dev = filp->private_data;
int ret;
DECLARE_WAITQUEUE(wait, current);
mutex_lock(&dev->mutex);
add_wait_queue(&dev->w_wait, &wait);
while (dev->current_len==GLOBALFIFO_SIZE) {
if(filp->f_flags & O_NONBLOCK) {
ret = -EGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE);
mutex_unlock(&dev->mutex);
schedule();
if(signal_pending(current)) {
ret = -ERESTARTSYS;
goto out2;
}
mutex_lock(&dev->mutex);
}
if(count > GLOBALFIFO_SIZE - dev->current_len)
count = GLOBALFIFO_SIZE - dev->current_len;
if(copy_from_user(dev->mem+dev->current_len, buf,count)) {
ret=-EFAULT;
goto out;
}else {
dev->current_len+= count;
printk(KERN_INFO “written %d byte(s), current_len:%d\n”, count,dev->current_len);
wake_up_interruptible(&dev->r_wait);
if(dev->async_queue) {
kill_fasync(&dev->async_queue,SIGIO, POLL_IN);
printk(KERN_INFO “%s kill SIGIO\n”, func);
}
ret = count;
}
out:
mutex_unlock(&dev->mutex);
out2:
remove_wait_queue(&dev->w_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
return ret;
}

**增加异步通知后的globalfifo设备驱动release()函数**

static int globalfifo_release(struct inode *inode, struct file *filp)
{
globalfifo_fasync(-1, filp, 0);
return 0;
}
“`

猜你喜欢

转载自blog.csdn.net/aaaa255116/article/details/81708169