ldd3上已經講了如何開發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的做法,和ldd3上說的一樣:
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的原理更爲複雜。
http://www.360doc.com/content/11/1214/23/1317564_172324612.shtml