天天看點

poll/select方式讀取event資訊一、poll功能介紹二、select方式

一、poll功能介紹

poll機制和select機制是完全一樣的,隻是App接口函數不一樣

poll/select函數可以傳入"逾時時間",這段時間内,如果條件滿足,就會立刻傳回(比如有資料可讀、有空間可寫),否則就會逾時,傳回錯誤。

1.1 poll用法

  1. App先調用open函數
  2. 準備

    struct pollfd

    ntds_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;
}
           

繼續閱讀