一,阻塞型字符驱动程序
1,等待队列的初始化
在 Linux 中, 一个等待队列由一个"等待队列头"来管理, 一个 wait_queue_head_t 类型的结构, 定义在<linux/wait.h>中. 可使用以下2种方法对等待队列初始化
(1)静态方法,定义并初始化一个等待队列头:
DECLARE_WAIT_QUEUE_HEAD(name);
(2)动态方法:
wait_queue_head_t my_queue;
init_waitqueue_head(&my_queue); //参数是指针
2,睡眠函数
Linux 内核中睡眠的简单函数集合
wait_event(queue, condition)
wait_event_interruptible(queue, condition) 【常用】
wait_event_timeout(queue, condition, timeout)
wait_event_interruptible_timeout(queue, condition, timeout)
在所有上面的形式中, queue 是要用的等待队列头.注意它是"通过值"传递的.
condition是一个任意的布尔表达式,这个宏在睡眠前后都会对这个布尔表达式求值,在条件值为真值前, 进程会保持睡眠.
3,唤醒函数
void wake_up(wait_queue_head_t *queue);
void wake_up_interruptible(wait_queue_head_t *queue);
注意它的参数是指针
wake_up 唤醒在给定队列上等待的所有进程,调用这个方法后如果条件condition值为假时,进程依然睡眠
二,POLL设备操作
1,应用程序select系统调用,
(1)函数原型
int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);maxfdp:文件描述符的范围,比待检测的最大文件描述符大1
readfds:被读监控的文件描述符集
writefds:被写监控的文件描述符集
exceptfds:被异常监控的文件描述符集
timeout:超时参数
timeout取不同的值,该调用有不同的表现:
timeout为0,不管是否有文件满足都立刻返回,无文件满足返回0,有文件满足则返回一个正值
timeout为NULL,select将阻塞进程,直到某个文件满足要求
timeout为正整数,这个数就是等待的最大值,select在timeout时间内阻塞
返回值:
1,正常情况下返回满足要求的文件描述符的个数
2,经过timeout等待时间仍无文件满足要求则返回0
3,如果select被某个信号中断,返回-1并置errno为EINTR
4,如果出错,返回-1,并置相应的errno
(2)select的使用方法
1,将要监控的文件添加到文件描述符集2,调用select开始监控
3,判断文件是否发生变化
(3)对描述符集操作的4个宏
FD_ZERO(fd_set *fdset); //清空文件描述符集fdset
FD_SET(int fd, fd_set *fdset); //将文件描述符fd添加到文件描述符集fdset
FD_CLR(int fd, fd_set *fdset); //在文件描述符集fdset中删除文件描述符fd
FD_ISSET(int fd, fd_set *fdset); //检测文件描述符集fdset中的文件fd是否发生了变化
2,驱动程序的POLL实现
应用程序调用select方法可能使进程阻塞,这个调用由驱动程序的poll方法实现,
(1)函数原型
unsigned int (*poll) (struct file *filp, poll_table *wait);
(2)在poll函数里的使用方法
1,调用poll_wait将等待队列添加到poll_table结构中,poll_wait原型:
void poll_wait (struct file *, wait_queue_head_t *, poll_table *);
2,返回描述设备是否可读或可写的掩码
POLLIN 如果设备可被不阻塞地读, 这个位必须设置.
POLLRDNORM 如果"正常"数据可用来读,这个位必须设置, 一个可读的设备返回( POLLIN | POLLRDNORM ).
POLLOUT 如果设备可被写入而不阻塞,这个位在返回值中设置,
POLLWRNORM 这个位和 POLLOUT 有相同的含义, 并且有时它确实是相同的数. 一个可写的设备返回( POLLOUT|POLLWRNORM).
(3)例子
static unsigned int scull_p_poll(struct file *filp, poll_table *wait)
{
struct scull_pipe *dev = filp->private_data;
unsigned int mask = 0;
/*
* The buffer is circular; it is considered full
* if "wp" is right behind "rp" and empty if the
* two are equal.
*/
down(&dev->sem);
poll_wait(filp, &dev->inq, wait);
poll_wait(filp, &dev->outq, wait);
if (dev->rp != dev->wp)
mask |= POLLIN | POLLRDNORM; /* readable */
if (spacefree(dev))
mask |= POLLOUT | POLLWRNORM; /* writable */
up(&dev->sem);
return mask;
}