poll的设计

#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "select_poll"
#define MAX_BUFFER_SIZE 20

static char buffer[MAX_BUFFER_SIZE];
static int buffer_char_count = 0;
static wait_queue_head_t my_queue;
struct semaphore sem;

static ssize_t demo_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
	ssize_t ret;
	
	if(buffer_char_count > 0){
		if(down_interruptible(&sem))
			return -ERESTARTSYS;
		if(copy_to_user(buf, buffer, buffer_char_count))
			return -EINVAL;
		//唤醒等待队列头指向的量表中的所有等待队列
		wake_up_interruptible(&my_queue);
		ret = buffer_char_count;
		buffer_char_count = 0;
		up(&sem);
		return ret;
	}
	else
		return 0;

	return ret;
}

static ssize_t demo_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
	ssize_t ret;

	if(down_interruptible(&sem))
		return -ERESTARTSYS;
	//休眠当前进程,知道condition满足
	wait_event_interruptible(my_queue, buffer_char_count == 0);
	//check condition.
	if(count > MAX_BUFFER_SIZE)
		return -EINVAL;
	if(copy_from_user(buffer, buf, count))
		return -EINVAL;

	ret = count;
	buffer_char_count = count;
	//Release semaphore.
	up(&sem);
	return ret;
}

unsigned int demo_poll(struct file *filp, struct poll_table_struct *wait)
{
	unsigned int mask = 0;
	if(down_interruptible(&sem))
		return -ERESTARTSYS;
	//将对应的等待队列头添加到轮询表中,pollwait函数不会阻塞,只是把当前进程添加到wait参数指向的轮询表中
	poll_wait(filp, &my_queue, wait);
	if(buffer_char_count > 0)
		mask |= POLLIN | POLLRDNORM;
	if(buffer_char_count == 0)
		mask |= POLLOUT | POLLWRNORM;
	up(&sem);
	return mask;
}

struct file_operations dev_fops = {
	.owner = THIS_MODULE,
	.read = demo_read,
	.write = demo_write,
	.poll = demo_poll,
};

struct miscdevice misc = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEVICE_NAME,
	.fops = &dev_fops,
};

static int __init demo_init(void)
{
	int ret = misc_register(&misc);
	init_waitqueue_head(&my_queue);
	sema_init(&sem, 1);
	printk("select poll init success.\n");
	return ret;
}

static void __exit demo_exit(void)
{
	misc_deregister(&misc);
	printk("select poll exit sucess.\n");
}

module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");



测试程序

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>

#define BUFFER_LEN	20

int main(void)
{
	int fd, num;
	fd_set rfds, wfds;
	char buf[BUFFER_LEN];
	
	memset(buf, 0, BUFFER_LEN);

	fd = open("/dev/select_poll", O_RDWR | O_NONBLOCK);

	if (fd != -1)
	{
		while(1){
			FD_ZERO(&rfds);
			FD_ZERO(&wfds);
			FD_SET(fd, &rfds);
			FD_SET(fd, &wfds);

			select(fd + 1, &rfds, &wfds, NULL, NULL);

			if(FD_ISSET(fd, &rfds)){
				printf("Data can be read!\n");
				read(fd, buf, BUFFER_LEN);
				memset(buf, 0, BUFFER_LEN);
			}

			if(FD_ISSET(fd, &wfds)){
				printf("Data can be written!\n");
			}

			sleep(1);
		}
	}
	else{
		printf("Device open failed!\n");
	}

	return 0;
}

测试方法:

echo xxxxxxxx > /dev/select_poll




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值