【Linux】I/O多路复用—select和pselect
select函数
#include <sys/select.h>
int select(int maxfdp1, fd_set *restrict readfds, fd_set *restrict writefds,
fd_set *restrict exceptfds, struct timeval *restrict tvptr);
返回值:准备就绪的描述符数目;若超时,则返回0;若出错,返回-1
参数:
-
tvptr
tvptr == NULL
永远等待。当所指定的描述符中有一个准备好或捕捉到一个信号则返回。如果捕捉到信号,则返回-1,errno置为EINTR。tvptr->tv_sec == 0 && tvptr->tv_usec == 0
根本不等待。测试所有指定的描述符并立即返回。tvptr->tv_sec != 0 || tvptr->tv_usec != 0
等待指定的秒数和微秒数。当有描述符准备好,或者当指定的时间值已超时则立即返回。如果超时,返回0。和第一种情况一样,这种等待会被信号中断。
readfds, writefds, exceptfds
指向描述符集的指针,分别是我们关心的可读、可写或处于异常条件的描述符集合。每个描述符集存储在一个fd_set数据类型中。任意一个指针都可以为空。-
fd_set类型
这个类型由实现决定,它可以为每个描述符保持一位,我们可以把它看作一个很大的字节数组。
对于该数据类型,只能进行如下处理:- 分配一个该类型变量
- 将一个该类型变量赋值给另一该类型变量
-
对该类型变量使用如下四个函数:
#include <sys/select.h> int FD_ISSET(int fd, fd_set *fdset); 返回值:fd在描述符集中,则返回非0值;否则,返回0 int FD_CLR(int fd, fd_set *fdset); //清除一位 int FD_SET(int fd, fd_set *fdset); //开启一位 int FD_ZERO(fd_set *fd_set); //将描述符集的所有位设置为0
这些接口可实现为宏或者函数。在声明一个描述符集之后,必须用FD_ZERO将该描述符集清零,然后再设置我们关心的描述符的位。
在select返回后,可使用FD_ISSET检查各描述符集中的指定位是否仍处于打开状态。
-
maxfdp1
该参数的意思是”最大文件描述符编号加1“。考虑所有3个描述符集,其中最大的描述符编号加1,就是该参数的值。通过指定该位,内核只在指定范围内寻找大开的位,而不必关心三个描述符集中没有使用的那些位。因为描述符编号从0开始,所以要给最大描述符编号加1,实际上该参数是要检查的描述符数。
返回值:
返回-1表示出错,这是可能的。例如在有描述符准备好之前,捕捉到一个信号。此时一个描述符集都不会被修改。
返回0,表示没有描述符准备好。此时,所有描述符集都会被置0。
一个正的返回值表明已经准备好的描述符数。该值是3个描述符集中准备好的描述符数之和,如果一个描述符既准备好读又准备好写,则在返回值中会计数两次。这种情况下,3个描述符集中仍旧打开的位对应已准备好的描述符。
注意:
- 一个描述符阻塞与否不影响select是否阻塞。
- 如果在一个描述符上遇到了文件末尾,select认为它是可读的。也就是说,到达文件末尾时,select并不会给一个异常提示
。
pselect函数
#include <sys/select.h>
int pselect(int maxfdp1, fd_set *restrict readfds, fd_set *restrict writefds,
fd_set *restrict exceptfds, const struct timespec *restrict tsptr
const sigset_t *restrict sigmask);
返回值:准备就绪的描述符数目;若超时,则返回0;若出错,返回-1
除下面几点外,pselect和select相同:
- pselect的超时值使用timespec结构,该结构以秒和纳秒表示超时值,能够提供更精确的超时时间。
- pselect的超时值被声明为const,这保证了超时值不会在调用时被修改。 pselect使用可选的信号屏蔽字。如果参数sigmask非空,则在函数被调用时,以原子的方式安装该屏蔽字,再返回时,恢复以前的屏蔽字。
上一篇: Java实现客户端与多线程服务器的通信(网络编程)
下一篇: 从已有项目中抽取 framework
推荐阅读
-
一篇文章帮你彻底搞清楚“I/O多路复用”和“异步I/O”的前世今生
-
Linux I/O多路复用详解及实例
-
【面试】一篇文章帮你彻底搞清楚“I/O多路复用”和“异步I/O”的前世今生
-
select模块(I/O多路复用)
-
I/O多路转接——select、poll 和 epoll
-
I/O 复用:select 、poll 和 epoll 函数
-
Linux网络编程 - I/O多路复用之epoll
-
Linux系统编程——I/O多路复用select、poll、epoll的区别使用
-
Linux下的select、poll、epoll等I/O复用函数(一)
-
Linux服务器--I/O复用(select、poll、epoll)