poll/select方式读取event信息

一、poll功能介绍

poll机制和select机制是完全一样的,只是App接口函数不一样
poll/select函数可以传入"超时时间",这段时间内,如果条件满足,就会立刻返回(比如有数据可读、有空间可写),否则就会超时,返回错误。

1.1 poll用法

  1. App先调用open函数
  2. 准备struct pollfdntds_t结构体
		struct pollfd fds[1];
		nfds_t nfsd = 1;
		
		fds[0].fd = fd;
		fds[0].events = POLLIN;
		fds[0].revents = 0;
  1. 构造poll函数
  2. 从poll的返回值中判断是否有数据,调用read立即读取event信息。
			 ret = poll(fds, nfsd, 5000);
        if(ret > 0) {
            if(fds[0].revents == POLLIN) {
                while(read(fd, &event, sizeof(event)) == sizeof(event)) {
                    printf("get event: type=0x%x, code=0x%x, value=0x%x\n",
                            event.type, event.code, event.value);
                }
            }
        } else if(ret == 0) {
            printf("poll time out\n");
        } else {
            printf("poll error\n");
        }

2.2 源码

#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>

//...

int main(int argc, char *argv[])
{
	int fd, err, len, i, bit, ret;
	unsigned char byte;
	struct input_id id;
	struct input_event event;
	unsigned int evbit[2];
	struct pollfd fds[1];
	nfds_t nfsd = 1;

	/* ./app /dev/input/event0 noblock */
	if(argc < 2) {
		printf("Usage: %s <dev> [noblock]\n", argv[0]);
		return -1;
	}

	if(argc == 3 && !strcmp(argv[2], "noblock")) {
		fd = open(argv[1], O_RDWR|O_NONBLOCK);
		printf("open block\n");
	} else {
		fd = open(argv[1], O_RDWR);
		printf("open nonblock\n");
	}
	if(fd < 0) {
		printf("open %s err\n", argv[1]);
		return -1;
	}

	err = ioctl(fd, EVIOCGID, &id);
	if(err == 0) {
		printf("bustype = 0x%x\n", id.bustype);
		printf("vendor  = 0x%x\n", id.vendor);
		printf("product = 0x%x\n", id.product);
		printf("version = 0x%x\n", id.version);
	}

	//....

	while(1) {
		fds[0].fd = fd;
		fds[0].events = POLLIN;
		fds[0].revents = 0;
		ret = poll(fds, nfsd, 5000);
		if(ret > 0) {
			if(fds[0].revents == POLLIN) {
				while(read(fd, &event, sizeof(event)) == sizeof(event)) {
					printf("get event: type=0x%x, code=0x%x, value=0x%x\n",
							event.type, event.code, event.value);
				}
			}
		} else if(ret == 0) {
			printf("poll time out\n");
		} else {
			printf("poll error\n");
		}
	}

	return 0;
}

二、select方式

2.1 slect编写流程

  1. 准备slect的参数
	int nfds;
	struct timeval tv;
	fd_set readfds;
  1. 准备好参数,使用FD_*的函数修改fd_set
		/* 设置超时时间 */
		tv.tv_sec  = 5;
		tv.tv_usec = 0;
		
		/* 想监测哪些文件? */
		FD_ZERO(&readfds);    /* 先全部清零 */	
		FD_SET(fd, &readfds); /* 想监测fd */
		nfds = fd + 1; /* nfds 是最大的文件句柄+1, 注意: 不是文件个数, 这与poll不一样 */ 
  1. 使用select,并判断后,read
		ret = select(nfds, &readfds, NULL, NULL, &tv);
		if (ret > 0)  /* 有文件可以提供数据了 */
		{
			/* 再次确认fd有数据 */
			if (FD_ISSET(fd, &readfds))
			{
				while (read(fd, &event, sizeof(event)) == sizeof(event))
				{
					printf("get event: type = 0x%x, code = 0x%x, value = 0x%x\n", event.type, event.code, event.value);
				}
			}
		}
		else if (ret == 0)  /* 超时 */
		{
			printf("time out\n");
		}
		else   /* -1: error */
		{
			printf("select err\n");
		}

2.2 源码

#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

char *ev_names[] = {
	"EV_SYN ",
	"EV_KEY ",
	"EV_REL ",
	"EV_ABS ",
	"EV_MSC ",
	"EV_SW	",
	"NULL ",
	"NULL ",
	"NULL ",
	"NULL ",
	"NULL ",
	"NULL ",
	"NULL ",
	"NULL ",
	"NULL ",
	"NULL ",
	"NULL ",
	"EV_LED ",
	"EV_SND ",
	"NULL ",
	"EV_REP ",
	"EV_FF	",
	"EV_PWR ",
};

int main(int argc, char *argv[])
{
	int fd, err, len, i, bit, ret;
	unsigned char byte;
	struct input_id id;
	struct input_event event;
	unsigned int evbit[2];
	struct pollfd fds[1];
	nfds_t nfsd = 1;
	fd_set rfds;
	int nfds = 0;
	struct timeval tv;

	/* ./app /dev/input/event0 noblock */
	if(argc < 2) {
		printf("Usage: %s <dev> [noblock]\n", argv[0]);
		return -1;
	}

	if(argc == 3 && !strcmp(argv[2], "noblock")) {
		fd = open(argv[1], O_RDWR|O_NONBLOCK);
		printf("open block\n");
	} else {
		fd = open(argv[1], O_RDWR);
		printf("open nonblock\n");
	}
	if(fd < 0) {
		printf("open %s err\n", argv[1]);
		return -1;
	}

	err = ioctl(fd, EVIOCGID, &id);
	if(err == 0) {
		printf("bustype = 0x%x\n", id.bustype);
		printf("vendor  = 0x%x\n", id.vendor);
		printf("product = 0x%x\n", id.product);
		printf("version = 0x%x\n", id.version);
	}

	len = ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), &evbit);
	if(len > 0 && len <= sizeof(evbit)) {
		printf("support ev type: ");
		for(i=0;i<len;i++) {
			byte = ((unsigned char *)evbit)[i];
			for(bit=0;bit<8;bit++) {
				if(byte & (1<<bit)) {
					printf("%s ", ev_names[i*8+bit]);
				}
			}
		}
		printf("\n");
	}

	while(1) {
		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);	//监测fd
		tv.tv_sec = 5;
		tv.tv_usec = 0;

		nfds = fd + 1;
		ret = select(nfds, &rfds, NULL, NULL, &tv);
		if(ret == -1)
			printf("select error\n");
		else if(ret) {
			if(FD_ISSET(fd, &rfds)) {
				while(read(fd, &event, sizeof(event)) == sizeof(event)) {
					printf("get event: type=0x%x, code=0x%x, value=0x%x\n",
							event.type, event.code, event.value);
				}
			}
		} else {
			printf("select time out\n");
		}
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

习惯就好zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值