• 从I/O事件到阻塞、非阻塞、poll到epoll的理解过程


    I/O事件

     

    I/O事件

    非阻塞I/O。在了解非阻塞I/O之前,需要先了解I/O事件

    我们知道,内核有缓冲区。假设有两个进程A,B,进程B想读进程A写入的东西(即进程A做写操作,B做读操作)。进程A需要先写入到内核缓冲区中,然后B从内核缓冲区中读取,如图:

    进程B会监听内核缓冲区的变化

    I/O事件的阻塞与同步

    1. 当内核缓冲区为空的时候,进程B会阻塞住
    2. 当A往内核缓冲区写入时,内核缓冲区就不是空状态了,这时候就会唤醒进程B
    3. 如果缓冲区满了,但是进程B没有被唤醒,就会通知进程A,告诉A不要再写入数据了,也就是进程A被阻塞
    4. 当进程B被唤醒后,B就从缓冲区读取数据,由于B在读数据,缓冲区就不会是满的状态了,这时候就会通知A继续写数据,也就是进程A被唤醒
    5. 如果进程A还没有唤醒,而缓冲区被B读完了(缓冲区为空),这时候就会阻塞进程B

    阻塞I/O的缺点

    在阻塞I/O情况下,一个线程只能处理一个流的I/O事件。也就是说,如果想处理多个流的I/O事件,就必须使用多进程(fork),或者多线程——效率太低

    处理I/O的第二种方法

    除了使用阻塞I/O,还可以使用非阻塞I/O的方式。
    最开始能想到的就是用轮询的方法:依次询问每个流,如果缓冲区不为空,就进行操作;

    否则,询问下一个流,但是这种方法效率很低,会白白浪费掉CPU资源于是便引入了代理——poll

    ========================================================================================================

    poll

    poll代理可以同时观察很多I/O流事件,在空闲的时候(即没有I/O事件的时候),会阻塞当前线程

    当有I/O事件的时候,会被唤醒,然后把所有流轮询一遍
    这样就能通过减少盲目的轮询来减少对CPU资源的浪费


    但是,使用这个也有缺点由于每次唤醒都需要把所有流都轮询一遍,当流很多的时候,轮询的时间会很长

     

    poll进化版——epoll

    epoll是基于事件的轮询,它会记录是哪个流产生了I/O事件,然后针对这个流来进行操作,大大降低了复杂度

    添加一个 学习  epoll的学习链接 http://blog.csdn.net/xiajun07061225/article/details/9250579

    还有一个reactor模式的学习链接 http://blog.csdn.net/u013074465/article/details/46276967

  • 相关阅读:
    线性表之链式存储结构
    最大公约数:辗转相除法
    字符串系列之:逆序输出字符串
    链表有关的常见面试题
    从数组中找出最大的和最小的数
    C语言实现简单线程池
    线性表之顺序存储结构
    新学了姜葱豆腐
    渗透1
    MySQL注入中新Tips
  • 原文地址:https://www.cnblogs.com/zhangkele/p/7777923.html
Copyright © 2020-2023  润新知