UNP学习第六章select

一、I/O复用典型的网络应用场合

  • 当客户处理多个描述字时,必须使用I/O复用,这在前一段中已做了描述。
  • 一个客户同时处理多个套接口时可能的,但很少出现。
  • 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。
  • 如果一个服务器即要处理TCP,又要处理UDP。
  • 如果一个服务器要处理多个服务或者多个协议。

 

二、I/O模型

一个输入操作一般有两个不同的阶段:

1.等待数据准备好

2.从内核到进程拷贝数据

 

五个I/O模型基本区别:

  • 阻塞I/O

 

此系统调用直到数据报到达切拷贝到应用缓冲区或是出错才返回。

  • 非阻塞I/O模型

 

前三次调用recvfrom任无数据返回,因此内核立即返回一个EWOULDBLOCK错误。

第四次调用recvfrom时,数据已准备好,被拷贝到应用缓冲区,recvfrom返回成功指示。

一直调用recvfrom称之为轮询,这会对CPU时间极大浪费。

  • I/O复用模型

调用select或poll,在这两个系统调用中的某一个上阻塞,而不是阻塞于真正的I/O系统调用。

我们阻塞select调用,等待数据报套接口可读。当select返回套接口可读条件时,我们调用recvfrom将数据报拷贝到应用缓冲区中。

这一种和第一种比较没有什么优越性,而且调用了两次系统调用。但是select可以等待多个描述字。

  • 信号驱动I/O模型

 我们也可以用信号,让内核描述字准备好时用信号SIGIO通知我们。

先要允许套接口进行信号驱动I/O,并通过系统调用sigaction安装一个信号处理程序。

此系统调用立即返回,进程继续工作,它是非阻塞的。数据准备好被读时,就为该进程生成一个SIGIO信号。

我们可以在信号处理程序中调用recvfrom来读取数据报,并通知主循环来处理。(也可以通知主循环读取)

信号的好处是,不阻塞,主循环可以继续执行。

  • 异步I/O模型

 

和上一个信号驱动I/O由内核通知我们何时可以启动一个I/O操作,异步I/O是由内核通知我们I/O操作何时完成。

 

三、select函数

#include <sys/select.h>
#include <sys/time.h>

int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset
    const struct timeval *timeout);
返回:准备好描述字的正数目0超时,-1出错
maxfdp1:整数值,集合中所有文件描述符范围,所有文件描述符中的最大值+1
readset:指向一组等待可读性检查的套接口
writeset:指向一组等待可写性检查的套接口
exceptset:指向一组等待错误检查的套接口
timeout:select()最多等待时间,对阻塞操作则为NULL

timeout有三种可能:

1.永远等待下去:仅在有一个描述字准备好I/O时才返回,为此,我们将参数timeout设置为空指针

2.等待固定时间:再有一个描述字准备好I/O后返回,但不超过timeout

3.根本不等待:检查描述字后立即返回,这称为轮询。timeout指向0

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

#include <sys/select.h>

int FD_ISSET(int fd, fd_set *fdset);  /*在调用select()函数后,用FD_ISSET来检测fd是否在set集合中,当检测到fd在set中则返回真,否则,返回假(0)*/
返回:若fd在描述符集中,返回非0值,否则返回0
void FD_CLR(int fd, fd_set *fdset);  /*将fd从set集合中清除*/
void FD_SET(int fd, fd_set *fdset);  /*将fd加入set集合*/
void FD_ZERO(fd_set *fdset);  /*将set清零使集合中不含任何fd*/

 相关的还有fd_set

typedef struct
{
/*XPG4.2requires this member name.Otherwise avoid the name
from the global name space.*/
#ifdef__USE_XOPEN
__fd_maskfds_bits[__FD_SETSIZE/__NFDBITS];
#define__FDS_BITS(set)((set)->fds_bits)
#else
__fd_mask__fds_bits[__FD_SETSIZE/__NFDBITS];
#define__FDS_BITS(set)((set)->__fds_bits)
#endif
}fd_set;

 

转载于:https://www.cnblogs.com/ch122633/p/8445114.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值