免费注册 查看新帖 |

Chinaunix

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

linux键盘驱动(模块动态加载)三 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-01-29 15:51 |只看该作者 |倒序浏览
linux键盘驱动(模块动态加载)三

上面如果你看得懂得话,那么可以进入下面的学习了,主要介绍的是内核定时器的使用,利用等待队列实现阻塞型I/O,poll系统调用,异步通知方式,介绍完之后,我将给出一个应用实例,对于有使用过文件操作系统调用的来说,对我们所写的键盘驱动来说,他们基本上是一样的。废话少说,我们马上开始我们精彩的驱动开发!
六.内核定时器的使用
    在该驱动中,我们假设对键盘的获取是以0.2s为周期执行。源代码如下
static struct timer_list timer;///////我们定义的定时器,也许你会问timer_list是什么来的,其实一看名称就应该就知道了,而为什么要用到list那么多定时器呢?其实在linux中还有很多相同的定义,比如说信号,我们定义的也是信号集,你可以定义该list是一个元素的,也可以是多个的。所以对于timer_list就可以这样描述:在未来某一个特定时刻执行某一系列特定任务的功能。下面我们还会给出内核中timer_list的具体描述,^_^好像我的话又说多了

static int Keypad_starttimer(void)
{
     init_timer(&timer);//初始化定时器结构
     timer.function=Keypad_timer;//超时服务程序
     timer.expires=jiffies+20;//当前时刻加0.2s
     add_timer(&timer);
     return 0;
}
///超时服务程序
static void Keypad_timer(unsigned long data)
{
    read_xy();
}
/////////接下来说下timer-list这个数据结构,如果你不感兴趣的话可以跳过,该结构在include\linux\timer.h中定义
struct timer_list
{
     struct list_head entry;
     unsigned long expries;
    spinlock_t lock;
    unsigned long magic;
    void (*function)(unsigned long);
    unsigner long data;
    struct tvec_t_base_s *base;
}
七.利用等待队列实现阻塞型I\O
     在用户程序执行读操作的时候有可能尚且没有数据可以读取,为此需要让read操作等待,直到有数据可以读取,这就是阻塞型i\o,阻塞型io可以通过使用进程休眠方法实现。在无数据可以读取的时候,采用等待队列让进程休眠,直到有数据到达的时候才唤醒进程完成数据的读操作。
    在本驱动中的read,若循环队列缓冲区中没有数据,则进程进入休眠态,定时器函数每隔0.2s读取键值一次,将按键状态放入缓冲并且适时唤醒进程读取数据。
   等待队列的使用流程如下:
   1.声明一个等待队列
   2.把当前进程加入到等待队列中
   3.把进程的状态设置为TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE;
   4.调用schedule,以让出cpu
  5.检测所需要的资源是否可用,若是,把当前进程从等待队列中删除,否则转3循环
接下来我们在对read中有关等待队列阻塞实现做具体的解释
static ssize_t Keypad_read(struct file *filp,char *buf,ssize_t count,loff_t *l)
{
   DECLEARE_WAITQUEUE(wait,current);//声明等待队列,将当前进程加入到等待队列中
   KEY_EVENT t;
   ulong out_buf[2];
   if(head==tail)//当前循环队列中没有数据可以读取
   {
        if(filp->f_flags & O_NONBLOCK)//假如用户采用的是非堵塞方式读取
             return _EAGAIN;
       add_wait_queue(&queue,&wait);//将当前进程加入等待队列
       current->state=TASK_INTERRUPTIBLE;//设置当前进程的状态
       while((head==tail)&&!signal_pending(current))//假若还没有数据到循环队列并且当前进程没有受到信号(该类信号具体来说是未决的休眠)
        {
              shedule();//进程调度
              current->state=TASK_INTERRUPTIBLE;
        }
        current->state=TASK_RUNNING;//该进程恢复执行
        remove_wait_queue(&queue,&wait);//移出等待队列
        if(head==tail)
           return count;
        t=get_data();//调用get_data()函数,得到缓冲区中的数据,下面将给予详细的 介绍
        out_buf[0]=t.status;
        out_buf[1]=t.click;
        copy_to_user(buf,&out_buf,sizeof(out_buf));//将得到的键值拷贝到用户数据区
        return count;
      
   }
}


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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP