网络编程中I/O复用模型

再回首一些概念

  • 阻塞IO
    • 数据没有准备好, 读操作就会阻塞
    • 数据不能立即被收时, 写操作就会阻塞
    • 打开文件时阻塞, 直到某些条件发生
  • 非阻塞IO
    • 立即返回, 并用错误值来表示当前的状态
  • 指定非阻塞方式
    • 打开时指定O_NONBLOCK 标志
    • 使用fcntl 打开或关闭非阻塞方式
  • 网络编程时, 可以使用非阻塞, 用轮询方式发送
  • 使用多线程可以避免使用非阻塞IO, 但是同步开销较大

多路IO

  • 当程序需要同时从多个文件描述符读数据时
    • 使用多进程/多线程, 同步复杂, 进程线程开销
    • 使用非阻塞IO, 交替轮询
    • 通过信号使用异步IO, 无法判断哪个IO完成
  • 多路IO: 把关心的IO放入一个列表/文件描述符集合, 调用多路函数
  • 多路IO函数阻塞, 直到有一个IO数据准备好后返回
  • 返回后告诉调用者哪个描述符准备好了

select实现说明

  • 调用select时通过参数告诉内核用户感兴趣的IO描述符
  • 关心的IO状态: 输入,输出或错误三种状态
  • 调用者等待指定的时间
  • 返回之后内核告诉调用者哪些个描述符准备好了
    • 哪些描述符发生了变化
  • 调用返回后对准备好的描述符调用读写操作
  • 不关心的描述符集合传NULL

函数详解

  • man手册

select() 
/* According to POSIX 1003.1-2001 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>    
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,  struct timeval *timeout);
  • 返回值:如果成功,返回所有sets中描述符的个数;如果超时,返回0;如果出错,返回-1。

  • 监视readfds来查看是否read的时候会被堵塞

    注意,即便到了end-of-file,fd也是可读的。

  • 监视writefds看写的时候会不会被堵塞。

  • 监视exceptfd是否出现了异常。

    主要用来读取OOB数据,异常并不是指出错。

  • 注意当一个套接口出错时,它会变得既可读又可写。

  • 如果有了状态改变,会将其他fd清零,只有那些发生改变了的fd保持置位,以用来指示set中的哪一个改变了状态。
  • 参数n是所有set里所有fd里,具有最大值的那个fd的值加1

与fd_set有关的函数

fd_set是一个位向量, 每位表示一个描述符

这里写图片描述

int FD_ISSET(int fd, fd_set *fdset);
//测试某个描述符是否在集合内用来指示一个fd是不是一个set的一部分。他很有用,用来看select后哪一个fd可用了。
void FD_CLR(int fd, fd_set *fdset);
//从集合内把一个描述符移除
void FD_SET(int fd, fd_set *fdset);
//把一个描述符加入集合
void FD_ZERO(fd_set *fdset);
//清空描述符集合

这里写图片描述

这里写图片描述

关于time_out

  • timeout是从调用开始到select返回前,会经历的最大等待时间。
  • 两种特殊情况:如果为值为0,会立刻返回。如果timeout是NULL,会阻塞式等待。
 struct timeval {
      long    tv_sec;     /* seconds */
      long    tv_usec;    /* microseconds */
  };
  • 一些调用使用3个空的set, n为zero, 一个非空的timeout来达到较为精确的sleep.

  • 为了较好的可移植性,timeout在循环中需要被重新赋初值。

  • timeout== NULL

    • 无限等待
    • 被信号打断时返回-1, errno 设置成 EINTR
  • timeout->tv_sec == 0 && timeout ->tv_usec == 0
    • 不等待立即返回
  • timeout->tv_sec != 0 || timeout ->tv_usec != 0
    • 等待特定时间长度, 超时返回0

注意事项

  • 可以把同一个描述符同时放入读和写集合
  • 当读和写准备好时, 返回值的计数分别加1次
  • 普通文件的三种状态总是返回准备好的状态
  • 是否阻塞式IO不会影响select的结果
  • 如果一个描述符到了文件结尾,select返回的状态是准备好
  • 对一个准备好的描述符, 读出长度是0表示到达结尾
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值