I/O多路复用概述

首先流是什么?
文件,socket,pipe等可以进行I/0操作的内核对象都是流.
流有两种基本的操作:读和写.
为了减少频繁的I/0操作,系统引入了内核缓冲区,即流的操作是在内核缓冲区中进行.
这里有四种基本操作场景:
1. 内核缓冲区为空,但线程A要去读数据,那么内核就会产生一个事件告诉线程A,我这里没数据,你需要等待(阻塞,不可读).
2. 当内核缓冲区有数据后,内核就产产生一个事件告诉线程A,我这里有数据了,你可以来读数据了(唤醒,可读).
3. 内核缓冲区满了,但线程B要往里面继续写数据,那么内核就会产生一个事件告诉线程B,我这里已经满了,你需要等待(阻塞,不可写).
4. 当内核缓冲区数据被读出去后,就会产生一个事件告诉线程B,我这里有空间了,你可以继续往里面写东西了(唤醒,可写).
以上四个场景对应了四个I/0事件.

线程对I/0的操作分为阻塞和非阻塞两种模式
阻塞:一个线程只能操作一个流,如果无法进行I/0操作,如内核缓存区没有数据进行读取,那么线程暂停运行,等待有数据后再运行,等待期间不能做其他事情.

非阻塞:一个线程可以同时操作多个流, 只有在所有流都无法操作的时候线程才会暂停运行.

linux系统设计了select,poll和epoll三种机制来处理非阻塞模式下的I/0操作,也就是I/O多路复用.

select的实现原理:
1. 将所有流的文件描述符拷贝到内核空间.
2. 遍历所有文件描述符,寻找可以操作的流.(无差别主动轮训)
3. 如果有文件已经就绪,那就操作这些已经就绪的文件,否则,线程就会暂停运行.在暂停期间,如果内核产生了I/0事件,那么线程恢复运行,否则暂停一段时间后自动恢复,再次遍历所有的文件描述符.

poll与select的实现方式类似.

epoll可以理解为event poll是对poll和select的改进
epoll并不会进行无差别的主动轮训,也就是不会主动去遍历所有文件描述符,而是先注册感兴趣的I/0事件,然后监听这个事件即可.
epoll有三个函数调用:
1. epoll_create 创建一个epoll对象,一般epollfd = epoll_create()
2. epoll_ctl(epollfd, EPOLL_CTL_ADD, socket, EPOLLIN);//注册缓冲区非空事件,即有数据流入
3. epoll_wait(epollfd,...)等待直到注册的事件发生


另外还有一个同步I/O和异步I/0的概念:
同步I/0:
在读写事件就绪后,应用程序需要自己把数据从内核空间拷贝到用户空间,拷贝时这个应用线程是阻塞的.
异步I/0:
在读写事件就绪后,I/O的实现会自动把数据从内核空间拷贝到用户空间,不需要应用程序线程去拷贝.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值