73.多路复用POLL在驱动中的应用

之前在网络的进程开发中,我们有学习过多路复用,这次我们将select,poll应用到我们的按键驱动中。

主要应用于单线程,单进程中同时读取多个设备或文件的情况。

具体可以复习下“42.Linux网络编程--IO多路复用”章节。

 

一 .POLL的函数实现

 

函数

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

参数

参数1: 表示多个文件描述符集合

                     struct pollfd描述的是文件描述符到信息

                     struct pollfd {

               int   fd;  //文件描述符

               short events;   //希望监控fd的什么事件:读,写,出错

                                                 POLLIN 读,

                                                 POLLOUT 写,

                                                 POLLERR出错

               short revents;    //结果描述,表示当前的fd是否有读,写,出错

                                                 //用于判断,是内核自动赋值

                                                 POLLIN 读,

                                                 POLLOUT 写,

                                                 POLLERR出错

                     };

参数2:被监控到fd的个数

参数3: 监控的时间:

                                   正: 表示监控多少ms

                                   负数: 无限的时间去监控

                                   0: 等待0ms,类似于非阻赛

返回值

返回值:负数:出错

              大于0,表示fd中有数据

              等于0: 时间到

 

二.使用Poll对设备文件进行监控

main.c

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

struct key_event{
	int code; // 表示按键的类型:  home, esc, Q,W,E,R,T, ENTER
	int value; // 表示按下还是抬起 1 / 0
};

#define KEY_ENTER		28

int main(int argc, char *argv[])
{
	int ret;
	struct key_event event;
	char in_buf[128];

	int fd = open("/dev/key0", O_RDWR);
	if(fd < 0)
	{
		perror("open");
		exit(1);
	}

	//监控多个文件fd
	struct pollfd pfd[2];

	pfd[0].fd = fd; //监控按键设备
	pfd[0].events = POLLIN;

	pfd[1].fd = 0; //标准输入
	pfd[1].events = POLLIN;
	
	while(1)
	{
            //poll只能执行一次,所以想一直监控要放在循环中
			ret = poll(pfd, 2, -1); // 驱动需要去实现poll接口,类似于open, read,
			printf("ret = %d\n", ret);
			
			if(ret > 0)
			{
				if(pfd[0].revents & POLLIN)
				{
					read(pfd[0].fd, &event, sizeof(struct key_event));
					if(event.code == KEY_ENTER)
					{
						if(event.value)
						{
							printf("APP__ key enter pressed\n");
						}else
						{
							printf("APP__ key enter up\n");
						}
					}
				}
				if(pfd[1].revents & POLLIN)
				{
					fgets(in_buf, 128, stdin);//如果没有poll就会一直阻塞在这里等待用户输入
					printf("in_buf = %s\n", in_buf);
				}
			}else{
				perror("poll");
				exit(1);
			}
	}

	close(pfd[0].fd);

	return 0;

}

key_dev.c驱动中添加poll接口

unsigned int key_drv_poll(struct file *filp, struct poll_table_struct *pts)
{
	// 返回一个mask值
	unsigned int mask;
	// 调用poll_wait,将当前到等待队列注册系统中
	poll_wait(filp, &key_dev->wq_head, pts);
	
	// 1,当没有数据到时候返回一个0
	if(!key_dev->key_state)
		mask = 0;

	// 2,有数据返回一个POLLIN
	if(key_dev->key_state)
		mask |= POLLIN;

	return mask;
}

const struct file_operations key_fops = {
	.open = key_drv_open,
	.read = key_drv_read,
	.write = key_drv_write,
	.release = key_drv_close,
	.poll = key_drv_poll,
	
};

这样就可以同时监控按键和屏幕输入。

资源占用也是非常低的。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值