POLL模型
Poll功能:监测文件描述符上,是否有某些事件发生 1.函数: #include<poll.h> int poll(struct pollfd *fds,unsigned int nfds,int timeout); 参数: (1)fds:是一个poll函数监听的struct pollfd结构类型的数组,每一个元素中,包含了三部分内容:文件描述符,监听的事件集合,返回的事件集合。 pollfd结构体定义如下: struct pollfd { int fd; //文件描述符(scoket描述符) short events; //等待的事件 short revents; //实际发生了的事件 }; event和revent的取值是一样的,常用的事件: POLLIN 有数据可读 POLLOUT 写数据不会导致堵塞 POLLMSGIGPOLL 消息可用 POLLERR 指定的文件描述发生错误
- nfds:和select函数的第一个参数相同,最大scoket描述符+1
- timeout:表示poll函数的超时时间,单位是毫秒(ms)
注意:timeout==0 代表立即返回 timeout>0 代表等待指定的毫秒数后,返回 timeout<0 代表永不过期,就是阻塞 poll的返回值:==0 等待超时 >0 正常返回 ==-1 错误 2.和select的区别 poll没有socket的FD_SETSIZE(1024)个数的限制 poll不用每次不会清理监测的socket的集合 不同与select使用三个位图来表示三个fdset的方式,poll使用一个Pollfd的指针实现。 3.poll的缺点 poll中监听的文件描述符数目增多时,则: 和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符 每次调poll都需要大量的pollfd结构从用户态拷贝到内核中。 同时连接的大量客户端在一时刻只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。
select模型: select用于IO复用,用于监视多个文件描述符的集合,判断是否有符合条件的事件发生。 函数select可以先对需要操作的文件描述符进行查询,查看是否目标文件描述符可以进行读写或者错误操作,然后当文件描述符满足操作的条件的时候才进行真正的IO操作 函数原型如下: int select(int nfds,//nfds最大文件描述符+1 fd_set*readfds,//监控的所有读文件描述符集合 fd_set *writes,//写集合 fd_set *exceptfds //异常集合 struct timeval *timeout);//超长时间 返回值:>0正常(正常情况下返回就绪的文件描述符个数) =0 超时 =-1 发生错误(select被某个信号中断它将返回-1并设置errno为EINTR) EBADF 文件描述词为无效的或该文件已关闭 EINTR 此调用被信号所中断 EINVAL 参数n为负值 #从某个文件描述符的集合中取出某个文件描述符 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); 注意:文件描述符的集合存在最大的限制,其最大值为FD_SETSIZE=1024 优点:与多进程多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程,线程,也不必维护这些进城线程,从而大大减小了系统的开销。I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是写就绪或读就绪),能通知程序进行相应的读写操作。 epoll模型: epoll是select和poll的增强版本,相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到一个内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。 epoll相关的函数: #include <sys/epoll.h> int epoll_create(int size); int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event): int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout)<