1.阻塞问题的几种解决模型
1.1 非阻塞模型:类似于死循环,需要适当加休眠,防止cpu占用太高;效率较低
1.2 线程异步:效率最高的一种解决方案
1.3 I/O多路转接与复用 select(低) pselect poll(较高) epoll(最高)(linux独有)
select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout))
由系统对文件描述符文件进行监听
参数:nfds:三个文件集里最大文件描述符加1;
readfds:监听的读事件文件描述符集合
writefds:监听的写事件文件描述符集合
exceptfds:意外事件的集合
timeout:超时退出设置,为0时不堵塞,为NULL时无时间限制
注:需要调用以下部分函数来对文件描述符集合来对需要监听的文件进行设置
void FD_CLR(int fd, fd_set *set); //把fd从集合里移除
int FD_ISSET(int fd, fd_set *set);//检查fd是否在集合里
void FD_SET(int fd, fd_set *set); //把fd加到集合里
void FD_ZERO(fd_set *set); //把集合清零
例:fd_set rds; //设置一个描述符集合
FD_ZERO(&rds); //清空集和
FD_SET(fds[0],&rds);//将fds[0]加入到集合中// fds[0]是一个管道的读端
FD_SET(STDIN_FILENO,&rds); //将标准文件输入加入到集合中
ret=select(fds[0]+1,&rds,NULL,NULL,NULL);//返回事件发生个数,没有事件发生则阻塞
注:当事件发生后,发生事件的文件描述符会继续留在sets中,其余被清除。
缺点:1.每次发生会更改集合sets,需要重新设置;
2.是轮询机制,如果文件描述符不连续会导致空循环
效率并不高,和非阻塞模型差不多。
下面两种使运用较多的方案:
1.poll()
2.epoll()