您的位置:首页 > 其它

高级字符驱动程序操作

2016-08-05 20:04 155 查看
通过读/写来实现数据传输,但除了数据传输之外,还有请求设备锁门、弹出介质、报告错误信息等。
休眠:当一个进程所需要的资源得不到满足时,会标记为一种特殊状态,该状态就可以理解为休眠,休眠中的进程会被搁置在一边,等待将来的某个事件发生。
对于休眠需要记住三天规则:
1)、永远不要在原子上下文中进入休眠(原子上下文是指:执行多个步骤时,不能有任何的并发访问);
2)、当我们被唤醒时,我们永远无法知道休眠了多长时间,或者休眠期间都发生了什么事情;
3)、除非我们知道有其他人在其他地方唤醒我们,否则进程不能休眠。
static ssize_t scull_p_read (struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
struct scull_pipe *dev = filp->private_data;

if (mutex_lock_interruptible(&dev->mutex))
return -ERESTARTSYS;

while (dev->rp == dev->wp) { /* nothing to read */
mutex_unlock(&dev->mutex); /* release the lock */
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
PDEBUG("\"%s\" reading: going to sleep\n", current->comm);
if (wait_event_interruptible(dev->inq, (dev->rp != dev->wp)))
return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
/* otherwise loop, but first reacquire the lock */
if (mutex_lock_interruptible(&dev->mutex))
return -ERESTARTSYS;
}
/* ok, data is there, return something */
if (dev->wp > dev->rp)
count = min(count, (size_t)(dev->wp - dev->rp));
else /* the write pointer has wrapped, return data up to dev->end */
count = min(count, (size_t)(dev->end - dev->rp));
if (copy_to_user(buf, dev->rp, count)) {
mutex_unlock (&dev->mutex);
return -EFAULT;
}
dev->rp += count;
if (dev->rp == dev->end)
dev->rp = dev->buffer; /* wrapped */
mutex_unlock (&dev->mutex);

/* finally, awake any writers and return */
wake_up_interruptible(&dev->outq);
PDEBUG("\"%s\" did read %li bytes\n",current->comm, (long)count);
return count;
}

分析scull_p_read是如何处理数据的:
while循环在拥有设备信号量时测试缓冲区,如果有数据,则立即将数据返回给用户而不需要休眠,这样整个循环就被跳过了。如果缓冲区为空,则需要释放信号量,必须进入休眠。释放信号量之后,快速检查用户请求是否是非阻塞I/O,如果是,则返回,否则调用wait_event_interruptible
 
 
异步通知:
使用异步通知,应用程序可以在数据可用时收到一个信号,而不需要不停地使用轮询来关注数据。
llseek实现:
适用于处理有明确定义的数据区,并不适用于只提供数据流(如串口和键盘)的设备
,在open方法中通过调用nonseekable_open来通知内核设备不支持llseek。
 
1、如何使进程休眠(并唤醒)?
使进程休眠可以有三种方式:a、简单休眠 
wait_event_interruptible(queue,
condition)queue是值传递而不是指针,condition是任意一个布尔表达式,休眠前后都要多这个表达式进行求值;b、高级休眠
首先是分配并初始化一个wait_queue_t结构,然后将其加入到对应的等待队列,接着设置进程的状态,将其标记为休眠,最后是检查休眠等待条件,成立则放弃处理器;c、手工休眠
prepare_to_wait和finish_wait
2、如何实现非阻塞I/O

显示的阻塞有filp->f_flags中的O_NONBLOCK标志决定。
3、设备可读取或写入时如何通知用户空间

4、如何在驱动程序中实现几种不同的设备访问策略?
5、驱动程序怎样实现异步信号?
a、F_SETOWN被调用时对filp->f_owner赋值;b、在执行F_SETFL启用FASYNC时调用驱动程序的fasync方法;c、当数据到达时,所有注册为异步通知的进程都会被发送一个SIGIO信号。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐