五种IO模型

阻塞IO模型

在内核将数据准备好之前, 进程将会一直等待, 直到内核将数据全部准备好

非阻塞IO模型

如果数据还没有准备好, 内核将会向当前进程返回一个 EWOULDBLOCK 错误码, 同时当前进程会不断的进行返回, 轮询式的取检查是否有数据准备好

信号驱动模型

要想实现信号驱动模型, 必须在之前给当前进程注册一个 SIGACTION 信号, 然后返回, 当内核中数据到达的时候, 此时就会出发SIGACTION信号, 当前进程收到该信号的时候, 此时就说明内核已经将数据准备好, 于是当前进程就通过 recvfrom 函数进行系统调用, 此时的进程在读取数据的时候一定不会阻塞,因为之前注册了信号SIGACTION信号, 只有事件发生的时候进程才会切换到内核态,于是就达到了非阻塞式的接受数据

IO多路转接

应用进程通过 select 一次关心多个文件描述符, 一旦用户关心的文件描述符变为可读状态的时候, 此时用户就会从内核中将数据读取,当数据读取完毕的时候, 此时进程从内核态转换到用户态.但是需要注意, 虽然多路复用和阻塞式IO看起来是相似的但是注意 在进行多路复用的时候, 当前进程只关心一个文件描述符, 但是多路复用一次会关心多个文件描述符.

异步IO

异步IO和信号启动优点相似, 但是不同的是异步IO数据的拷贝是由内核完成, 而且只有当内核将数据全部拷贝完成的时候, 此时通过调用aio_read中的指定信号通知当前进程数据此时已经准备好

同步通信和异步通信

所谓同步通信就是发起者在发起一次调用的时候, 如果没有接受到结果, 此时这个调用就不能反回.即调用者会主动等待这个调用的结果
所谓异步信号就是当前进程在进行调用的时候, 此时这个调用就会立刻返回, 即就是在调用者发起调用的时候,调用者不会立即得到返回结果, 而这个返回结果通常是通过状态或者回调函数来通知调用者

阻塞和非阻塞

阻塞指的是当前进程如果关心一个时间, 那么此时的进程在自己关心的时间发生之前就会一直等待, 直到自己关心的时间发生, 此时该进程才会返回
非阻塞指的是进程关心一个事件, 但是当这个事件发生之前当前进程会去看一下是否自己关心的事件处于就绪状态,如果当前事件就绪, 则处理当前事件, 如果当前自己关心的事件不处于就绪状态,此时就会返回, 但是在这个过程中进程会不断进行探索, 以查看当前自己关心的事件是否处于就绪状态

重定向
int dup(int oldfd);
int dup2(int oldfd, int newfd);

其中dup和dup2都表示的是输出重定向,表示将当前最小的文件描述符重定向到oldfd中

IO多路复用select
select 函数原型
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exception, struct timeval* timeout);

其中参数nfds表示的关心的文件描述符的下最大值加1, writefd 表示的是关心的读文件描述符集, exception 表示的是关心你的异常文件描述符,timeout表示的是进程等待的时间
其中timeout设为NULL的时候表示的是当前进程处于阻塞状态, 当timeout设为0的时候, 代表的是当前进程值关心设置了的文件描述符上的事件, 不关心设置以外的文件描述符, 当timeout设置为一个值的时候, 此时表示如果在该时间内没有事件发生, 此时就直接返回

函数返回值

执行成功则返回关心的文件描述符中状态改变的个数
返回0代表的是在状态此改变之前timeout超时,此时没有返回的文件描述符
返回-1时则代表的是出错

select 就绪条件

读就绪
socket内核中, 接收的字节数大于低水位标识, 此时就可以无阻塞的进行读
当建立 TCP 连接的时候, 此时如果对端已经关闭对应的连接, 此时如果继续对SOCK进行读便会返回0
sock上有未处理的错误
监听的sock上有新的连接
写就绪
socket内核中发送的数据大于等于低水位标记的时候, 此时就可以进行无阻塞的写操作
对一个写操作被关闭的socket进行写, 此时便会出发 SIGPIPE 信号
socket使用非阻塞connect连接成功或失败之后
socket上有未读取的数据

select 的特点

可以监控的文件描述符集的个数受到 sizeof(fdset)的限制
每次加入监控集的时候, 必须对原来老的监控集进行保存, 保存的目的就是为了查看是否有新的文件描述符上的事件处于就绪, 第二个目的就是因为select在返回的时候会将原来就绪事件未发生的文件描述符对应的比特位进行清除, 所以必须保存

select的缺点

每次需要树洞对文件描述符集合进行手动的设置,使用时接口也不是特别好用
每次在调用的时候都必须将内核态的文件描述符集全部拷贝到用户态, 这个势必就会增加开销
每次在返回的时候都得一次遍历所传进来的fd, 增加了开销, 花费时间
select时间上关心 的文件描述符的个数受到sizeof(fdset) 的大小限制

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值