apue I/O多路转接,select与poll
2017-10-24 09:37
281 查看
I/O多路转接
select
传向select的参数告诉内核:我们所关心的描述符。
对于每个描述符,我们所关心的状态(是否读一个给定的描述符?是否写一个给定的描述符?是否关心一个描述符的异常状态?)。
愿意等待多长时间(可以永远等待,等待一个固定量时间,或完全不等待)。
从select返回时,内核告诉我们:
已经准备好的描述符的数量。
对于读、写或异常这三个状态中的每一个,哪些描述符已经准备好。
#include <sys/select.h> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 返回值:准备就绪的文件描述符数,若超时则返回0,若出错则返回-1.
先说明最后一个参数,它指定愿意等待的时间:
struct timeval { long tv_sec; // 秒 long tv_usec; // 微妙 };
有三种情况:
timeout==NULL,永远等待。当所指定的文件描述符中的一个已准备好或捕捉到一个信号则返回。如果捕捉到一个信号,则select返回-1,errno设置为EINTR。
timeout->tv_sec==0 && timeout->tv_usec==0,完全不等待。
timeout->tv_sec!=0 || timeout->tv_usec != 0,等待指定的秒数和微妙数。当指定的描述符之一已准备好,或当指定的时间已经超过时立即返回,超时时返回0。与第一种情况一样,这种等待也可能被信号中断。
中间的三个参数readfds、writefds和exceptfds是指向描述符集的指针。这三个描述符集说明了我们关心的可读、可写或处于异常条件的各个描述符。描述符集使用fd_set类型表示。
对fd_set类型可以进行的处理是:分配一个这种类型的变量;将这种类型的一个变量值赋予同类型的另一个变量;或对于这种类型的变量使用下列四个函数。
#include <sys/select.h> // 判断fd是否在set中 int FD_ISSET(int fd, fd_set *set); 返回值:若fd在描述符集中则返回非0值,否则返回0。 // 将fd添加到set集合中 void FD_SET(int fd, fd_set *set); // 将fd从set中移除 void FD_CLR(int fd, fd_set *set); // 将set清零 void FD_ZERO(fd_set *set);
中间参数中的任意一个或全部都可以是空指针,这表示对应的状态并不关心。如果三个指针都是空指针,那么select提供了比sleep更精确的定时器。
select的第一个参数nfds需要传入“最大的描述符加1”。在三个描述符集中,找出最大的描述符值,然后加1。
select的变体pselect:
#include <sys/select.h> /** * @param nfds 最大描述符加1 * @param readfds 读描述符集 * @param writefds 写描述符集 * @param exceptfds 异常描述符集 * @param timeout 超时时间 * @param sigmask 信号屏蔽字 * @return 准备就绪的描述符个数,若超时则返回0,失败返回-1 */ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);
除了一下几点,pselect和select相同:
select的超时值用timeval定义,pselect的超时值使用timespec定义。timespec使用秒和纳秒表示超时值。pselect的超时值为const。
pselect可以指定信号屏蔽字。在调用pselect时原子的安装信号屏蔽字,在返回时,恢复以前的信号屏蔽字。
poll
poll函数类似于select,poll的定义如下:#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout)
与select不同,poll不是每个状态(可读性、可写性和异常状态)构造一个描述符集,而是统一的放在pollfd数组中,每个数组元素指定一个描述符以及对其关心的状态。
struct pollfd { int fd; // 描述符 short events; // 对该描述符的哪些事件感兴趣 short revents; // 该描述符哪些事件发生了 };
nfds说明数组fds的长度。
events可以设置为下面表格中的值。函数返回时,内核设置revents成员,说明在该描述符上发生了哪些事件。
表14-6中,头四行测试可读性,接着三行测试可写性,最后三行测试异常状态。最后三行是由内核在返回时设置的。即使在events中没有指定这三个值,如果相应条件发生了,在revents中仍然会设置它们。
当一个描述符被挂断(POLLHUP)后,就不能再写该描述符。但是仍可从该描述符读取数据。
poll的最后一个参数说明我们愿意等待的时间,与select一样,有三种情况:
1. timeout == -1,永远等待。当所指定的描述符中有一个准备好或则捕捉到一个信号时返回。
2. timeout == 0,不等待。测试所有描述符并立即返回。
3. timeout > 0,等待timeout毫秒。当指定的描述符之一准备好,或指定的时间超时时立即返回。超时返回0。
相关文章推荐
- 多路转接之poll和select
- 多路复用 I/O 多路转接 select / poll / epoll
- I/O多路转接select/poll/epoll的对比
- I/O多路转接(select、pselect和poll)使用
- I/O多路转接之select、poll、epoll
- I/O多路转接之select、poll、epoll
- 高级I/O多路转接之select poll epoll 区别
- UNIX环境高级编程——I/O多路转接(select、pselect和poll)
- 高性能服务器——I/O多路转接的三种模式(select &poll& epoll)
- UNIX环境高级编程——I/O多路转接(select、pselect和poll)
- I/O多路转接复用机制---select,poll,epoll
- UNIX环境高级编程——I/O多路转接(select、pselect和poll)
- 【Nginx】I/O多路转接之select、poll、epoll
- 深入研究socket编程(2)——I/O多路转接(select、pselect和poll)
- 服务器与客户端的模型之select的多路转接
- IO多路复用之select、poll、epoll详解
- select - I/O多路转接全面透析
- 简单的多路复用编程(I/O)----select()和poll函数的运用
- 网络通信 --> IO多路复用之select、poll、epoll详解
- 【Linux】I/O多路转接select