码迷,mamicode.com
首页 > 其他好文 > 详细

I/O多路复用---select

时间:2016-07-30 15:12:27      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:i/o多路复用---select

 常见的linux服务器类型

    1.多进程并发服务器

    2.多线程并发服务器

    3.select多路I/O转接服务器

    4.poll多路I/O转接服务器

    5.epoll多路I/O转接服务器

 

       多路IO是指单个线程通过记录跟踪每一个 IO流的状态同时来管理多个IO流,尽量提高服务器的吞吐量

     与多进程多线程相比IO多路复用的计数最大优势就是系统开销小,不必创建进程/线程,也不必维护 进程/线程


 IO多路复用使用场景

(1)当客户处理多个描述符时(一般是交互式输入或网络套接口)

(2)当一个客户同时处理多个套接口时

(3)如果一个TCP服务器即要处理监听套接口又要处理UDP一般使用IO复用

(4)如果一个服务器要处理多个服务或协议


   select,poll,epoll都是多路复用的机制。所谓的多路复用机制就是通过一种机制可以监视多个文件描述符,一旦某个文件描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作,但是select,poll,epoll本质上都是同步IOd因为他们都需要在读写事件就绪后自己负责进行读写,也就是说读写过程是阻塞的,而异步IO无需自己负责读写,异步IO的实现会负责把数据从内核拷贝到用户控件

1.函数参数

int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* execptfds, struct timeval* timmeout);

nfds:监控的文件描述符集里最大的文件描述符加1

readfds:监控有读数据到达文件描述符集合,传入传出参数

writefds:监控有写数据到达文件描述符集合,传入传出参数

execptfds:监控异常发生文件描述符集合

timeout:设置阻塞监控呢时间

         NULL:永远等下去

         timeval:等待固定的时间

         timeval里时间均为 0,检查描述符字后立即返回,轮询

void FD_ZERO(fd_set* set);把文件描述符集合里初始化0

void FD_SET(int fd,fd_set* set);把文件描述符里fd位置 置1

void FD_CLR(int fd,fd_set* set);把文件描述 符里fd位置 置0

int FD_ISSET(int fd,fd_set* set);测试文件描述符集合里的fd是否为1,有1返回1,没1返回0

2.函数返回值

执行成功返回文件描述词状态已改变的个数

如果返回 0表示词状态改变前已经超过指定 时间,没有返回

当发生错误时返回-1,错误原因可能是errno,此时参数readfds,writefds,exceptfds和timeout的值变得不可预测

错误的值可能为

EBADF;文件描述词无效或该文件已经关闭 

EINTR:此调用被信号中断

EINVAL:参数为负值

ENOMEN:核心内存不足

3.函数模型

理解select模型的关键在于理解fd_set,通常fd_set长度为1字节,fd_set中每一个bit可以对应一个文件描述符fd,则一字节长的fd_set可以对应8个fd

(1)执行fd_set set:FD_ZERO(&set)则set用位表示为0000 0000

(2)若fd=5,执行FD_SET(fd,&set)后set变为 0001,0000(第5位置1)

(3)若再加 fd=2,fd=1则set会变为0001,0011

(4)执行select(6,&set,0,0,0)阻塞等待

(5)执行fd=1,fd=2都发生 可读事件则select返回,此时 set变为0000,0011没有事件发生的fd=5被清空

基于以上特点有以下总结:

(1)可控文件描述符的个数取决于sizeof(fd_set)的值

(2)将fd加入select监控集时还要再使用一个数组保存放到监控集中的fd,一是用于返回后arr作为源数据和fd_set进行判断,二是select返回后会把以前加入的但并无事件发生的fd清空,每次开始select之前都要进行重新从arr取得Fd逐一加入,扫描arr的同时取得fd罪的的maxfd,用于作为select的第一个参数

(3)所以select模型 必须在 select前循环arr(加fd,取maxfd),select返回后循环arr(FD_ISSET判断是否有事件发生)

4.select的缺点

(1)每次调用都需要把fd从用户态拷贝到内核态,这个开销在fd很多时会很大

(2)每次调用select都需要在内核遍历传进来的所有fd,这个开销也很大

(3)select支持的文件描述符太小 ,默认 只有1024

(4)select会修改函数传入的参数数组,当这个函数 被调用很多次的时候就会发生错误

(5)

实现过程

(1)创建监听套接字

技术分享

(2)设置端口复用 127.0.0.1

指定族:IPv4

指定端口号并转化为网络字节序列

指定Ip并转化为网络字节序列

技术分享

(3)绑定到监听套接字

(4)将客户端数组 全部初始化为 -1

技术分享

(5)监听描述集初始化,并将监听套接字加到监听集

技术分享

(6)如果客户端有链接 请求,则将链接请求添加到监听集合里,然后判断下标i的是否大于当前文件描述符,每次都求取最大的文件描述符 ,一次轮询,当数组 满了的时候关闭当前客户端请求

技术分享

技术分享

技术分享















I/O多路复用---select

标签:i/o多路复用---select

原文地址:http://10808695.blog.51cto.com/10798695/1831987

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!