epoll详解

linux中存在许多I/O流,文件流,socket流等等。无论是文件,还是管道,我们都可以称之为流。

通过read操作,我们可以从流中读入数据,通过write操作,我们可以往流写入数据。

大部分文件都是存储在磁盘而非主存,频繁的I/O会使程序性能降低,所以linux存在缓冲区,引入缓冲区是为了减少频繁的I/O调用。

有了缓冲区之后,我们大部分的操作都是在缓冲区中进行。



这里假设我们有一个缓冲区Zone,进程A为写入,进程B为读出,缓冲区有如下状态:

缓冲区非空:

    一开始缓冲区为空,进程B读出阻塞,然后进程A写入数据,这时候缓冲区非空,内核就会产生一个事件告诉进程B可以读取了。

缓冲区满:

    如果进程B已经接收到可读取的时间消息,但是迟迟未读消息(可能睡着了吧),这个时候进程A还在写数据,使缓冲区满,内核就会产生一个事件告诉进程A你该停止写入了。

缓冲区非满:

    进程B终于醒过来了(简直是猪),慢慢消费了缓冲区中的数据,使缓冲区非满,这时内核就会产生一个事件告诉进程A可以接着写了。

缓冲区空:

    进行A写累了,停止写入,进行B还在傻傻地一直读,缓冲区的数据被消费光了,使缓冲区空,这时内核就会产生一个事件告诉进程B你该停止读取了。



同步阻塞I/O模式:

    一个线程只能处理一个流的I/O事件,要想同时处理多个流,就必须使用多线程。


同步非阻塞I/O模式:

    采用忙轮询的方式,一个线程可以同时处理多个流:   

 
 
  1. while true {
  2.    for i in stream[]{
  3.    if i has data
  4.        read until unavailable
  5.    }
  6. }

    虽然这个线程会不断地询问所有流是否有数据,但是如果所有的流都没有数据,CPU会造成空转。


多路复用I/O模式:

    为了避免CPU空转,我们引入select代理,该代理同时观察许多流的I/O事件,在空闲的时候,阻塞当前线程,当有事件的时候,才唤醒当前线程。        

  
  
  1. while true {
  2.    select(streams[])
  3.    for i in streams[] {
  4.        if i has data
  5.            read until unavailable
  6.    }
  7. }

    这种模式虽然解决了CPU空转的问题,当没有I/O事件产生,程序就阻塞在select处。当有I/O事件产生,只能进行无差别的轮询,无论这个流是否真的有数据,都会被轮询到。处理的流越多,每一次无差别轮询的事件就越长


epoll模式:

    不同于忙轮询和无差别轮询,epoll可以告诉我们哪个流发生了事件,相比于无差别轮询(只能告知我们所有的流中存在事件)进步了很多,此时我们只需要获取所需要的处理的流并对其进行处理即可

  
  
  1. while true {
  2. active_stream[] = epoll_wait(epollfd)
  3. for i in active_stream[] {
  4. read or write till
  5. }
  6. }









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值