免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 946 | 回复: 0
打印 上一主题 下一主题

linux下at91rm9200 RTC实时时钟驱动程序部分等待对列wait_queue简单理解 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-13 09:06 |只看该作者 |倒序浏览

linux下at91rm9200 RTC实时时钟驱动程序部分等待对列wait_queue简单理解
文章来源:http://gliethttp.cublog.cn
1.wait_queue_head_t类型
  wait_queue_t类型
  DECLARE_WAIT_QUEUE_HEAD(at91_rtc_wait)宏
  DECLARE_WAITQUEUE(wait, current)宏
  均在include/linux/wait.h中有定义
2.static DECLARE_WAIT_QUEUE_HEAD(at91_rtc_wait);
  定义队列头at91_rtc_wait,以后等待相应事件发生的应用程序将创建一个包含应用程序自身足够信息的wait队列,然后将那个wait队列
  作为at91_rtc_wait双向链表的第一个链表元素插入,队列头at91_rtc_wait原来的第一个双向链表元素将被链接成双向链表的第2个元素
3.at91_rtc_read读取函数的理解
gliethttp 2007-06-14驱动学习
ssize_t at91_rtc_read(struct file * file, char *buf, size_t count, loff_t * ppos)
{
    DECLARE_WAITQUEUE(wait, current);     //对于多个应用程序分别同时调用at91_rtc_read,那么每个应用程序都对应一个局部
    unsigned long data;                   //变量wait,DECLARE_WAITQUEUE宏将每个应用程序对应的cpu上下文current存放到
    ssize_t retval;                       //相应应用程序占有的局部变量wait中
    if (count  sizeof(unsigned long))
        return -EINVAL;
    add_wait_queue(&at91_rtc_wait, &wait);//将当前应用程序局部变量wait插入到at91_rtc_wait队列头,作为第一个链表元素
    set_current_state(TASK_INTERRUPTIBLE);//设置当前进程为可中断,那么任何对该应用程序的信号操作,都会唤醒该应用程序
    for (;;) {                            //使得应用程序能够从schedule();函数返回,继续执行for(;;)循环体
        spin_lock_irq(&at91_rtc_lock);
        data = rtc_irq_data;
        if (data != 0) {
            rtc_irq_data = 0;
            break;
        }
        spin_unlock_irq(&at91_rtc_lock);
        if (file->f_flags & O_NONBLOCK) {
            retval = -EAGAIN;
            goto out;
        }
        if (signal_pending(current)) {
            retval = -ERESTARTSYS;
            goto out;
        }
        schedule();
    }
    spin_unlock_irq(&at91_rtc_lock);
    data -= 0x100;        
    retval = put_user(data, (unsigned long *) buf);
    if (!retval)
        retval = sizeof(unsigned long);
out:
    set_current_state(TASK_RUNNING);
    remove_wait_queue(&at91_rtc_wait, &wait);
    remove_wait_queue(&at91_rtc_update, &wait);
    return retval;
}
举一个例子来说:如果有5个应用程序p1,p2,p3,p4,p5都试图调用了at91_rtc_read读取数据,那么将会有5个wait局部变量w1,w2,w3,w4,w5被创建,每个局部变量都存储着相应应用程序的足够调度信息,假设5个应用程序的创建的顺序是p1->p2->p3->p4->p5,那么at91_rtc_wait队列头中的5个待唤醒的进程wait的链接顺序为at91_rtc_wait->w5->w4->w3->w2->w1。
3.at91_rtc_interrupt中断函数的配对理解
gliethttp 2007-06-14驱动学习
static void at91_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    unsigned int rtsr = AT91_SYS->RTC_SR & AT91_SYS->RTC_IMR;
    if (rtsr) {
        if (rtsr & AT91C_RTC_ALARM)
            rtc_irq_data |= (AT91_RTC_AF | AT91_RTC_IRQF);
        if (rtsr & AT91C_RTC_SECEV)
            rtc_irq_data |= (AT91_RTC_UF | AT91_RTC_IRQF);
        if (rtsr & AT91C_RTC_ACKUPD)
            wake_up_interruptible(&at91_rtc_update);
        rtc_irq_data += 0x100;
        AT91_SYS->RTC_SCCR = rtsr;
        //gliethttp 2007-06-14
        wake_up_interruptible(&at91_rtc_wait);//将唤醒at91_rtc_wait队列头中包含了5个进程调度信息的5个wait对应的应用程序
        kill_fasync(&at91_rtc_async_queue, SIGIO, POLL_IN);
    }
}
小结:多个wait_queue的链接是通过双向链表完成的,wait_queue结构中含有struct list_head task_list;双向链表结构域,所以所有
      多个wait_queue之间的关联操作都是通过list_add(),list_del(),list_entry()等链表函数简单的完成。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/41638/showart_1411361.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP