poll
管理多个描述符进行轮询操作(查询文件描述符,如果有指定的时间发生立刻返回), 根据描述符的状态进行处理。一般通过返回值来确实指定的事件是否发生。没有文件描述符多少的限定。Poll函数退出后,struct pollfd 变量的fd,events,值被清零,revents变量包含了监测结果
阻塞、非阻塞
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
指定时间内轮询指定文件描述符,如果有指定事件发生返回一个真值。参数解释如下:
fds 是一个 struct pollfd 定义的结构体指针。
struct pollfd {
int fd; /* file descriptor */ 文件描述符
short events; /* requested events */ 请求事件
short revents; /* returned events */ 返回事件
};
事件定义如下:
常量 | 说明 |
|
POLLIN | 普通或优先级带数据可读 |
|
POLLRDNORM | 普通数据可读 |
|
POLLRDBAND | 优先级带数据可读 |
|
POLLPRI | 高优先级数据可读 |
|
POLLOUT | 普通数据可写 |
|
POLLWRNORM | 普通数据可写 |
|
POLLWRBAND | 优先级带数据可写 |
|
POLLERR | 发生错误 |
|
POLLHUP | 发生挂起 |
|
POLLNVAL | 描述字不是一个打开的文件 |
|
事件定义可以理解为 linux 内核层和应用层的约定,内核返回相应数据应用层接收进行判断可以知道哪些定义事件发生,一般最常用为 POLLIN。对于此参数我们只需要填充要轮询的文件描述符以及指定的事件即可
第二个参数 nfds 一般指定为 1,表示要轮询的文件个数, 其实就是第一个参数数组的大小。 如果只轮询一个
文件就指定为 1 即可。
timeout 表示超时时间,单位为 ms,指定为需要的大小即可。
-1:永远等待
0:立即返回,不阻塞这里
>0:等待的多少时间
返回值:
>0;fd数组中准备好读,写或出错状态的那些文件描述符的数量
=0:超时
<0:调用函数失败
3.1 定义
select 相对于 poll 接口来说要稍微复杂一些, 使用 fd_set 来描述指定文件的操作, poll 是通过返回值确定事件是否发生, select 是通过宏检验位进行确定, 但是大致作用几乎相同。
3.2 函数接口
我们也可以通过 select 函数再指定时间内轮询操作接口。
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
函数返回,会清空readfds、 writefds、 exceptfds三个集合,还有timeout的值,所以想检测他们,则需要在调用结束后再次设置
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
检验指定文件是否有指定的动作(有数据可读,有数据写),然后执行操作。
参数解释:
1、nfds:所监测文件描述符中,最大的文件描述符+1。 fd = open();
打开5个,fd1-fd5 要检测fd2,fd4, 则nfds为fd4+1
2、readfds、 writefds、 exceptfds:指定文件的动作集合,需要绑定,绑定前需要使用 FD_ZERO 清零, 再用 FD_SET 进行设置。 例如检验是否有数据可读:
fd_set fd_read;
FD_ZERO(&fd_read);//清空集合
FD_SET(fd,&fd_read);//添加要检测的集合
使用select函数轮询每个
int FD_ISSET(int fd,fd_set *set)//判断set集合中fd的状态是否发生变化
3、结构体 struct timeval 为指定轮询时间, 定义如下:
NULL:阻塞
0:非阻塞
指定时间:
struct timeval
{
long tv_sec; /* second */ //秒
long tv_usec; /* microsecond */ //微秒
返回值:
>0:执行成功,返回文件描述符状态已经改变的个数
=0:代表已经超过timeout时间,文件描述符状态还没有改变
=1:函数有错误,错误原因存在error,此时参数readfds、 writefds、 exceptfds,timeout的值变成不可预测:
错误值可能为:
EBADF:文件描述符为无效或者该文件已关闭
EINTR:次调用被信号中断
EINVAL:参数n为负值
ENOMEM:核心内存不足