高级字符驱动程序操作

来源:互联网 发布:淘宝店铺怎样实名认证 编辑:程序博客网 时间:2024/05/07 23:45

通过读/写来实现数据传输,但除了数据传输之外,还有请求设备锁门、弹出介质、报告错误信息等。

休眠:当一个进程所需要的资源得不到满足时,会标记为一种特殊状态,该状态就可以理解为休眠,休眠中的进程会被搁置在一边,等待将来的某个事件发生。

对于休眠需要记住三天规则:

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_waitfinish_wait

2、如何实现非阻塞I/O

显示的阻塞有filp->f_flags中的O_NONBLOCK标志决定。

3、设备可读取或写入时如何通知用户空间

4、如何在驱动程序中实现几种不同的设备访问策略?

5、驱动程序怎样实现异步信号?

aF_SETOWN被调用时对filp->f_owner赋值;b、在执行F_SETFL启用FASYNC时调用驱动程序的fasync方法;c、当数据到达时,所有注册为异步通知的进程都会被发送一个SIGIO信号。

0 0
原创粉丝点击