高级I/O之I/O多路转接

本文来自个人博客:https://dunkwan.cn

I/O多路转接

函数selectpselect

在所有POSIX兼容的平台上,select函数时我们可以执行I/O多路转接。传给select的参数告诉内核:

  • 我们关心的描述符
  • 对于每个描述符我们所关心的条件
  • 愿意等待多长时间

select返回时,内核告诉我们:

  • 已准备好的描述符总数
  • 对于读、写或异常这3个条件中每一个,哪些描述符已准备好
#include <sys/select.h>
int select(int maxfdpl, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict tvptr);
返回值:准备就绪的描述符数目;若超时,返回0;若出错,返回-1

tvptr参数指定愿意等待的时间长度。分为以下三种情况:

tvptr == NULL

永远等待。如果捕捉到一个信号则中断此无限期等待。当所指定的描述符中的一个已准备好或捕捉到一个信号则返回。如果捕捉到一个信号,则select返回-1,errno设置为EINTR

tvptr->tv_sec == 0 && tvptr->tv_usec == 0

根本不等待。测试所有的指定的描述符并立即返回。这是轮询系统找到多个描述符状态而不阻塞的select函数的方法。

tvptr->tv_sec != 0 || tvptr->tv_usec != 0

等待指定的秒数和微秒数。当指定的描述符之一已准备好,或当指定的时间值已经超过时立即返回。如果在超时到期时还没有一个描述符准备好,则返回值是0。与第一种情况一样,这种等待可被捕捉到的信号中断。

readfdswritefdsexceptfds参数是分别指向我们关心的可读、可写和处于异常条件的描述符集合。我们可以将这三个参数中的每一个都视为一个很大的字节数组。

对于fd_set数据类型的可以进行的处理是:分配一个这种类型的变量,将这种类型的一个变量赋给同类型的另一个变量,或对这种类型的变量使用以下4个函数中的一个。

#include <sys/select.h>
int FD_ISSET(int fd, fd_set *fdset);
返回值:若fd在描述符集中,返回非0值;否则,返回0void FD_CLR(int fd, fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
void FD_ZERO(fd_set *fdset);

FD_ISSET :测试描述符集中的某一个指定位是否打开

FD_SET:开启描述符集中的一位

FD_CLR:清除一位

FD_ZERO:将一个fd_set变量的所有位设置为0

POSIX.1还定义了一个pselect函数,该函数是select的一个变体。

#include <sys/select.h>
int pselect(int maxfdpl, fd_set *restrict readfds, fd_set *restrict exceptfds, const struct timespec *restrict tsptr, const sigset_t *restrict sigmask);
返回值:准备就绪的描述符数目;若超时,返回0;若出错,返回-1

除了以下几点外,pselectselect相同。

  • select的超时值用timeval结构相同,但pselect使用timespec结构。
  • pselect的超时值被声明为const,这保证了调用pselect不会改变此值。
  • pselect可使用可选信号屏蔽字。sigmaskNULL,那么在与信号有关的方面,pselect的运行状况和select相同。否则,sigmask指向一信号屏蔽字,在调用pselect时,以原子操作的方式安装该信号屏蔽字。在返回时,恢复以前的信号屏蔽字。

函数poll

poll函数可用于任何类型的文件描述符。

#include <poll.h>
int poll(struct pollfd fdarray[], nfds_t nfds, int timeout);
返回值:准备就绪的描述符数目;若超时,返回0;若出错,返回-1

poll函数第一个参数是由pollfd数组构成,这个数组中的每个元素指定一个描述符编号以及对该描述符感兴趣的条件。以下是该结构体。

struct pollfd{
    int fd;		   /* file descriptor to check, or < 0 to ignore */
    short events;  /* events of interest on fd */
    short revents; /* events that occurred on fd */
};

fdarray数组的元素个数由nfds指定。

events可设置为下图中的一个或多个,这些值告诉内核我们关心的是每个描述符的哪些事件。返回时,revents由内核设置,用于说明每个描述符发生了哪些事件。

timeout参数3种不同情形。

  • timeout == -1

    永远等待。当所指定的描述符中的一个已准备好,或捕捉到一个信号时返回,如果捕捉到一个信号,则poll返回-1,errno设置为EINTR

  • timeout == 0

    不等待。测试所有描述符并立即返回。这是一种轮询系统的方法,可以找到多个描述符的状态而不阻塞poll函数。

  • timeout > 0

    等待timeout毫秒。当指定的描述符之一已准备好,或timeout到期时立即返回。如果 timeout到期时还没有一个描述符准备好,则返回值是0。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值