参考:http://www.cnblogs.com/Anker/p/3265058.html
select
/* According to POSIX.1-2001 */
#include <sys/select.h> /* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h> int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *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); #include <sys/select.h> int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask);
select例子
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h> int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval; /* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(, &rfds); /* Wait up to five seconds. */
tv.tv_sec = ;
tv.tv_usec = ; retval = select(, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */ if (retval == -)
perror("select()");
else if (retval)
printf("Data is available now.\n");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.\n"); exit(EXIT_SUCCESS);
}
优点:实现简单,执行效率高,兼容性好,当描述符集合活跃度较高时,性能可能优于epoll。
select的几大缺点:
(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
(3)select支持的文件描述符数量太小了,默认是1024
poll
#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout);
功能和select类似,接口不同,优缺点和select类似,解决了select的缺点(3)
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);
int epoll_pwait(int epfd, struct epoll_event *events,
int maxevents, int timeout,
const sigset_t *sigmask);
优点:解决了select的三个缺点,适合并发量大,活跃量小的情况下。
缺点:epoll实现复杂一些。
epoll_create:创建epoll句柄,返回epoll对应的文件描述符epfd。linux 2.6.8之后,size被忽略,大于0即可。出错,-1,errno;
epoll_ctl:
op:
EPOLL_CTL_ADD:添加fd;
EPOLL_CTL_MOD:修改*event;
EPOLL_CTL_DEL:删除fd,*event忽略,可为NULL;
*event:
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t; struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
events:
- EPOLLIN 对应文件可读
- EPOLLOUT 对应文件可写
- EPOLLRDHUP (since Linux 2.6.17) 流套接字对等关闭连接或写半关闭
- EPOLLPRI 有紧急数据可读
- EPOLLERR 文件描述符出错,epoll_wait总是监听此事件,不需要设置
- EPOLLHUP 文件描述符挂起,epoll_wait总是监听此事件,不需要设置
- EPOLLET 设置 ET 模式,默认 LT 模式
- EPOLLONESHOT (since Linux 2.6.2) 只监听一次事件,监听完成这次事件后,不再监听,若需要,可再次epoll_ctl加入
epoll_wait:监听epfd中的事件
*events:保存发生时间;
maxevents:大于0,返回值最大不超过此值;
timeout:超时设置;