Linux——(十三)高级IO

1、常见的典型IO模型

阻塞IO、非阻塞IO、信号驱动IO、异步IO、
IO,输入输出,过程分为两步,一步是等待IO就绪,一步是拷贝数据,对数据进行对应的处理。

例子:钓鱼,是为了做好吃的鱼,满足口腹之欲

1.1 阻塞IO

  1. 我去钓鱼,把鱼饵抛入水里,接下来- -直等浮漂抖动,因为抖动就表示有鱼了,要是浮漂不动,我就一直等着

阻塞IO:为了完成IO操作,发起IO调用,若是当前不具备IO完成的条件,则调用不返回,一直等待
在这里插入图片描述

1.2 非阻塞IO

  1. 我去调鱼,觉得一直盯着浮漂,有点浪费实际,所以我就不一直等着浮漂了,而是打一把游戏,打完了再看。

非阻塞IO:为了完成IO操作,发起IO调用,若是当前不具备lO完成的条件,则调用立即报错返回
在这里插入图片描述

1.3 信号驱动IO

  1. 我去钓鱼,为了更加实时,我就给鱼竿上绑了了一个小铃铛,然后在抛下鱼饵后,我就开始打王者,等到铃铛响了开始钓鱼

信号驱动IO:为了提高资源利用率,先自定义IO就绪信号,当收到就绪信号,则表示IO就绪,这时候发起调用直接拷贝数据
在这里插入图片描述

1.4 异步IO

  1. 我去钓鱼,但是我钓鱼的目的是为了做鱼吃,我调用的时候带着我小姐妹,让我小姐妹钓鱼,钓上来顺便给我做,做好了再叫我。

异步IO:别人把事情做好了再来叫我,发起一个异步IO调用,IO操作由系统完成,完成后通知进程。
在这里插入图片描述

1.5 小结

1.5.1 阻塞与非阻塞

  1. 阻塞:为了完后一个操作发起调用,若当前不具备完后条件,则调用不返回
  2. 非阻塞:为了完成一个操作发起调用,若当前不具备完成条件,则报错返回
  3. 阻塞与非阻塞:通常用于讨论一个接口的特性,通常发起一个接口调用之后,接口是否能够立即返回。

1.5.2 同步与异步

  1. 同步:这个同步不是同步互斥的同步,而是同步异步的同步。这里描述的是一个操作流程。操作自己完成,一个完成之后,才能进行下一步。(阻塞和非阻塞就是属于同步的,一个完成才能进行下一个)
  2. 异步:操作由系统来完成,不用非等到一个完成才能进行下一个,而是可以直接发起下一个操作,操作完成后系统会通知进程。
    异步阻塞:发起异步操作后,等待系统完后。
    异步非阻塞:发起异步操作后,不等待系统完后,操作接口直接返回
  3. 同步与异步:通常用于讨论操作流程思想。(操作是由自己一个一个按流程完成,还是发起操作由系统完后后通知自己)

2、多路转接模型

也称为多路转接、多路复用。
作用:针对大量描述符的IO进行就绪事件监控。告诉我们进程哪个描述符就绪了什么事件。这时候我们可以针对就绪了的描述符进行对应的操作。不需要对没有就绪的描述符进行操作。进而导致程序阻塞或者效率降低。
就绪事件:描述符可读、可写、异常
技术实现:select模型、poll模型、epoll模型。

2.1 select模型

针对大量描述符进行IO就绪时间监控
IO就绪事件:
可读:一个描述符的接收缓冲器中的数据大小大于低水位标记(一个基准判断值:默认1字节)
可写:一个描述符的发送缓冲区中的剩余空间大小大于低水位标记(一个基准判断值:默认1字节)
异常:一个描述符产生了异常(比如一个连接断开了,描述符被关闭了,描述符没有打开…)

2.1.1 select操作流程

  1. 用户定义一个指定事件的描述符集合(三种:可读,可写,异常),进行初始化。
    struct fd_set{}
    这个结构体只有一个数组成员,被当做位图使用,用于1024个比特位,取决于——FD_SETSIZE大小。
    void FD_ZERO(fd_set *set);//初始化,清空集合

  2. 然后将需要监控指定事件的描述符添加到指定集合中(例如:对描述符监控可读事件,将其添加到可读事件描述符集合中)。
    void FD_SET(int fd , set* set)//添加fd描述符到Set集合中(其实就是把对应的比特位置1)

  3. 将集合中的数据拷贝到内核中,开始监控,当某个描述符就绪了指定要监控的事件,或者监控超时了则监控返回。
    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
    参数nfds是需要监视的最大的文件描述符值+1;
    rdsetfds,wrsetfds,exsetfds分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集合及异常文件描述符的集合;
    struct timeval timeout{time_t tv_set; time_t tv_usec;} 所设置的监控超过时间。
    参数timeout为结构timeval,用来设置select()的等待时间。

函数返回值:
执行成功则返回文件描述词状态已改变的个数
如果返回0代表在描述词状态改变前已超过timeout时间,没有返回值。当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds, exceptfds和timeout的值变成不可预测。

  1. 在监控返回之前,select会将事件描述符集合中未就绪的描述符从集合中删除掉。(这时候集合中的描述符都是就绪描述符)。
  2. 用户遍历所有监控的描述符,看哪个还在哪个集合中,则表示这个描述符就绪了什么事件,进而进行对应操作。
    int FD_ISSET(int fd, fd_set *set); // 用来测试描述词组set中相关fd 的位是否为真(判断fd描述符是否在set集合中)
  3. 如果不想监控某个描述符了,则可以移除监控(就是把描述符从监控集合中移除掉)
    void FD_CLR(int fd, fd_set *set); // 用来清除描述词组set中相关fd 的位
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值