poll函数
poll函数起源于SVR3,最初局限于流设备。SVR4取消了这种限制,允许poll工作在任何描述字上。poll提供的功能与select类似,不过在处理流设备时,它能够提供额外的信息。
#include <poll.h> int pollresult = poll(struct pollfd *fdarray, unsigned long nfds, int timeout);
第一个参数fdarray是指向一个结构数组第一个元素的指针。每个数组元素都是一个pollfd结构:
struct pollfd{ int fd; //descriptor to check short events; //events of interest on fd short revents; //events that occurred on fd };
结构数组中的 events 成员指定要测试的条件,而返回的结果则在保存在 revents。常用条件及含意说明如下:
poll函数可用的测试值
常量 | 说明 |
POLLIN | 普通或优先级带数据可读 |
POLLRDNORM | 普通数据可读 |
POLLRDBAND | 优先级带数据可读 |
POLLPRI | 高优先级数据可读 |
POLLOUT | 普通数据可写 |
POLLWRNORM | 普通数据可写 |
POLLWRBAND | 优先级带数据可写 |
POLLERR | 发生错误 |
POLLHUP | 发生挂起 |
POLLNVAL | 描述字不是一个打开的文件 |
注意:后三个只能作为描述字的返回结果存储在revents中,而不能作为测试条件用于events中。
第二个参数nfds是用来指定数组fdarray的长度。
最后一个参数timeout是指定poll函数返回前等待多长时间。它的取值如下:
timeout值 | 说明 |
-1 | 永远等待 |
0 | 立即返回,不阻塞进程 |
>0 | 等待指定数目的毫秒数 |
返回的结果pollresult
-1 | poll函数调用失败 |
0 | 在timeout内,数组fdarray中没有任何文件描述符准备好读、写或出错,poll函数正常超时返回。 |
>0 | 数组fdarray中准备好读、写或出错状态的那些文件描述符的总数量 |
之后根据 fdarray[0].revents & POLLIN来判断是哪个发生了变化,之后直接read就可以了。
例子
#include <stdio.h>
#include <poll.h>
#include <linux/inotify.h>
#include <string.h>
#define OPEN_MAX 3
#define PATH_MAX 3
#define READ_MAX 1000
int main(int argc,char *argv[]){
char *path = "/root/test/poll_test";
char *paths[PATH_MAX] = {
"/dev/input/event0",
"/dev/input/event2"
};
struct pollfd client[OPEN_MAX];
char read_buf[READ_MAX];
struct inotify_event *event;
char *event_buf[512];
printf("poll_test ...\n");
int fd = inotify_init();
if(fd != -1){
int wd = inotify_add_watch(fd,path,IN_DELETE | IN_CREATE);
client[0].fd = fd;
client[0].events = POLLIN;
printf("open inotify\n");
}else{
printf("error:inotify can't open.\n");
return -1;
}
int i;
for(i = 1;i<OPEN_MAX; i++){
fd = open(paths[i-1],O_RDWR);
if(fd != -1){
client[i].fd = fd;
client[i].events = POLLIN;
printf("open %s\n",paths[i-1]);
}else{
printf("error:%s can't open.\n",paths[i]);
return -1;
}
}
printf("ok. start loop.\n");
int pollresult = 0;
while(1){
if(pollresult == -1){
printf("error.\n");
return -1;
}else if(pollresult == 0){
}else{
if(client[0].revents & POLLIN){ //判断
size_t len = read(client[0].fd,event_buf,512);
event = (struct inotify_event *)(event_buf);
if(event->mask & IN_CREATE){
printf("notify:add %s \n",event->name);
}else{
printf("notify:delete %s \n",event->name);
}
}
for(i = 1;i<OPEN_MAX;i++){
if(client[i].revents & POLLIN){ //判断
int readsize = read(client[i].fd,read_buf,READ_MAX);
printf("read:%s\n",read_buf);
}
}
}
printf("polling...\n");
pollresult = poll(client,OPEN_MAX,-1); //轮询
}
}