一、poll功能介紹
poll機制和select機制是完全一樣的,隻是App接口函數不一樣
poll/select函數可以傳入"逾時時間",這段時間内,如果條件滿足,就會立刻傳回(比如有資料可讀、有空間可寫),否則就會逾時,傳回錯誤。
1.1 poll用法
- App先調用open函數
- 準備
和struct pollfd
結構體ntds_t
struct pollfd fds[1];
nfds_t nfsd = 1;
fds[0].fd = fd;
fds[0].events = POLLIN;
fds[0].revents = 0;
- 構造poll函數
- 從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編寫流程
- 準備slect的參數
int nfds;
struct timeval tv;
fd_set readfds;
- 準備好參數,使用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不一樣 */
- 使用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;
}