Linux驱动程序学习笔记(7)—— 阻塞、POLL

来源:互联网 发布:ipadmini安装不了软件 编辑:程序博客网 时间:2024/05/22 08:02

一,阻塞型字符驱动程序

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;
}


原创粉丝点击