epoll的理论与IO阻塞机制

流?I/O操作? 阻塞?

(1)流

▪ 可以进⾏I/O操作的内核对象

▪ ⽂件、管道、套接字……

▪ 流的⼊⼝:⽂件描述符(fd)

(2)I/O操作

所有对流的读写操作,我们都可 以称之为IO操作。

(3)阻塞

阻塞等待 不占⽤CPU宝贵的时间⽚

⾮阻塞忙轮询 占⽤CPU,系统资源

在处理意⻅数据的接收场景时, 我们建议优先选择阻塞等待的⽅ 式, 不浪费性能资源

(4)阻塞等待缺点:

不能够很好的处理 多个(I/O)请求的问题

同⼀个阻塞,同⼀时刻只能处理⼀个流的阻塞监听

(5)多路IO复⽤

既能够阻塞等待,不浪费资源

也能够同⼀时刻监听多个IO请求的状态

解决阻塞死等待的缺点(如何解决⼤量IO请求读写的问题)

⽅法⼀ : 阻塞等待+多进程/多线程

需要开辟线程浪费资源

⽅法⼆:⾮阻塞+忙轮询

while true {
    for i in 流[] {
       if i has 数据 {
         读 或者 其他处理
      }
   }
}        

CPU在⼤量的做判断,while和for

cpu的利⽤率不⾼

方法三:多路IO复⽤机制   select(与平台⽆关)

监听的IO数量有限,默认是1024个

不会精准的告诉开发者,哪些IO是可读可写的,需要遍历

while true {
    select(流[]); //阻塞
     //有消息抵达
    for i in 流[] {
        if i has 数据 {
            读 或者 其他处理
        }
    }
}                    

方法四:多路IO复⽤机制  epoll(Linux)

通过 /proc/sys/fd/file-max查看)

while true {
    可处理的流[] = epoll_wait(epoll_fd); //阻塞
     //有消息抵达,全部放在 “可处理的流[]”中
    for i in 可处理的流[] {
        读 或者 其他处理
    }
}    

epoll 的API

(1) 创建EPOLL

int epoll_create(int size);

(2) 控制EPOLL

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

(3) 等待EPOLL

int epoll_wait(int epfd, struct epoll_event *event, int maxevents, int timeout);

(4) 使⽤epoll编程主流程⻣架

触发模式

⽔平触发:

⽔平触发的主要特点是,如果⽤户在监听epoll事件,当内核有事件的时候,会拷⻉给⽤户态事 件,但是如果⽤户只处理了⼀次,那么剩下没有处理的会在下⼀次epoll_wait再次返回该事 件。

默认就是⽔平触发模式

边缘触发:

边缘触发,相对跟⽔平触发相反,当内核有事件到达, 只会通知⽤户⼀次,⾄于⽤户处理还是不处理, 以后将不会再通知。这样减少了拷⻉过程,增加了性能,但是相对来说,如果⽤户⻢⻁忘记处理,将会产 ⽣事件丢的情况。

在给事件进⾏绑定的时候,通过EPOLLET来设置

原文地址:https://www.cnblogs.com/peteremperor/p/13727189.html