IO复用简介
IO复用使得程序能同时监听多个文件描述符,这对提高程序的性能至关重要。通常,网络程序在下列情况下需要使用IO复用技术:
- 客户端程序要同时处理多个socket。
- 客户端程序要同时处理用户输入和网络连接。
- TCP服务器同时处理监听socket和连接socket。
- 服务器要同时处理TCP请求和UDP请求。
Linux下实现IO复用的系统调用主要有select、poll和epoll。
select系统调用
select系统调用的用途是:在一段指定时间内,监听用户感兴趣的文件描述符上的可读、可写和异常事件。
select API
select系统调用的原型如下:
#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd, fd_set *readfds, fd_set *writefds, fe_set *exceptfds, const struct timeval *timeout);
2)readfds、writefds和exceptfds参数分别指向可读、可写和异常等事件对应的文件描述符中集合。应用程序调用select函数时,通过这3个参数传入自己感兴趣的文件描述符。select调用返回时,内核将修改它们来通知应用程序哪些文件描述符已经就绪。这3个参数是fd_set结构体指针类型。
由于位操作过于繁琐,我们应该使用下面的一系列宏来访问fd_set结构体中的位:
由于位操作过于繁琐,我们应该使用下面的一系列宏来访问fd_set结构体中的位:
void FD_CLR(int fd, fd_set *fdset) /* 清除fdse所有位.*/
int FD_ISSET(int fd, fd_set *fdset) /* 测试fdset的位fd是否被设置 */
void FD_SET(int fd, fd_set *fdset) /* 设置fdset的位fd */
void FD_ZERO(fd_set *fdset) /* 清除fdset的位fd */
struct timeval {
long tv_sec; // seconds
long tv_usec; // and microseconds
};
由上定义可知,select给我们提供了一个微秒级的定时方式。如果给timeout变量的tv_sec成员和tv_usec