Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1337497
  • 博文数量: 482
  • 博客积分: 13297
  • 博客等级: 上将
  • 技术积分: 2890
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-12 16:25
文章分类

全部博文(482)

文章存档

2012年(9)

2011年(407)

2010年(66)

分类: LINUX

2011-05-06 19:07:32

上已经讲了如何开发linux下的驱动程序,怎么让该设备支持poll(和epoll),但是不够详细,这里给个例子。假设实现一个misc设备,为了实现poll,当然要有个wait_queue,注意,是dev带wait_queue,我一疏忽把wait_queue带到file上去了,调了半天才发现这个低级错误。


struct sample_dev

{

    struct miscdevice       misc;

    wait_queue_head_t    wait;

};


static struct sample_dev    s_dev;


s_dev这个设备现在既可以当miscdevice用,同时又有了wait_queue


struct file_operations sample_fops =

{

    .owner       = THIS_MODULE,

    .read         = sample_read,

    .write        = sample_write,

    .poll           = sample_poll,

};


static int __init init_sample(void)

{

    s_dev.misc.minor = MISC_DYNAMIC_MINOR;

    s_dev.misc.name = "poll_device_sample";

    s_dev.misc.fops  = &sample_fops;

    init_waitqueue_head(&s_dev.wait);

    return misc_register(&s_dev.misc);

}


static void __exit exit_sample(void)

{

    misc_unregister(&s_dev.misc);

}


这是设备的注册和注销。下面看sample_poll的做法,:


unsigned int sample_poll(struct file* file, poll_table* wait)

{

    unsigned int    mask = 0;


    poll_wait(file, &s_dev.wait, wait);


    /* if have something to read (代码省略)*/

        mask |= POLLIN;

    /* if have something to write (代码省略)*/

        mask |= POLLOUT;

    /* if some error occur (代码省略)*/

        mask |= POLLERR;


    return mask;

}


poll_wait是linux内核提供的,标准做法,所以最好这么用。在poll_wait里,current进程挂在了s_dev的wait_queue里,只有两种情况让他醒来:一个是poll系统调用超时(poll_table负责),另一个是读写唤醒他(后面的代码)。


sszie_t    sample_read(struct file* file, char __user* buff, loff_t* pos)

{

    /* do what you want to read(代码省略)*/

    wake_up_interruptible(&s_dev.wait); 

}


由于读走了一些数据,缓冲区(代码没有详细写)有位置了,可以往里面写了,上面标红的行便唤醒随眠的进程,他(进程)醒来后就到了poll_wait语句的后面,开始查看缓冲区并置mask,最后返回。sample_write也是同样的实现方式。


以上代码只是例子,并不完整,但原理已经充分。这样实现的设备已经可以支持poll和epoll调用,当然,epoll的原理更为复杂,和上面说的过程有一些差异,详情可以。

====

阅读(625) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~