概述
目录
- epoll中两种触发模式介绍
- 水平触发
- 边沿触发
- 为什么一定要把边沿触发和非阻塞io一起使用呢
- 解决方法
- 抛砖引玉
- 欢迎大家批评指正,共同进步
epoll中两种触发模式介绍
水平触发
水平触发,就是指在条件满足时,epoll_wait函数会一直来通知你,那么什么是这个条件呢? 这个条件就是指,假如我们在epoll_wait的第一个参数,也就是红黑树的树根中,加入的都是读事件,比如下面这样的
event.events = EPOLLIN | EPOLLET;
event.data.fd = server_socket;
epoll_ctl(efd, EPOLL_CTL_ADD, server_socket, &event)
那么我们第一次没有将缓冲区中的数据全部读出,那么epoll_wait函数还会继续通知我们,上面提到的条件可以理解成 缓冲区还有东西可以读
边沿触发
就像高低电平一样,只有从高电平到低电平或者低电平到高电平时才会通知我们,还是上面这个例子,假如我们没有把数据读完,那么epoll_wait函数便不再会通知我们,因为他已经通知过了,是否把缓冲区的数据读完和epoll没关系,这时只有客户端再次向服务器端发送数据,epoll_wait才会返回
为什么一定要把边沿触发和非阻塞io一起使用呢
如果这里使用阻塞IO,那么也就是说,假如我们一次从缓冲区中读取10个字节,但是客户端只发了五个过来,那么我们的IO就会阻塞住,因为缓冲区的东西不够读,这时候其他客户端再次发送消息,epoll_wait也不会返回,因为上一次epoll_wait返回之后,代码卡在了读取这里,这样服务器就无法处理其他数据了。
但是如果使用非阻塞IO,缓冲区的数据不够读了,那就不读了,读写函数马上返回,不再等待,这样就解决了上面的问题
解决方法
参考man文档,输入man epoll
Level-triggered and edge-triggered
The epoll event distribution interface is able to behave both as edge-triggered (ET) and as level-triggered (LT). The difference between the
two mechanisms can be described as follows. Suppose that this scenario happens:
1. The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance.
2. A pipe writer writes 2 kB of data on the write side of the pipe.
3. A call to epoll_wait(2) is done that will return rfd as a ready file descriptor.
4. The pipe reader reads 1 kB of data from rfd.
5. A call to epoll_wait(2) is done.
If the rfd file descriptor has been added to the epoll interface using the EPOLLET (edge-triggered) flag, the call to epoll_wait(2) done in
step 5 will probably hang despite the available data still present in the file input buffer; meanwhile the remote peer might be expecting a
response based on the data it already sent. The reason for this is that edge-triggered mode delivers events only when changes occur on the
monitored file descriptor. So, in step 5 the caller might end up waiting for some data that is already present inside the input buffer. In
the above example, an event on rfd will be generated because of the write done in 2 and the event is consumed in 3. Since the read operation
done in 4 does not consume the whole buffer data, the call to epoll_wait(2) done in step 5 might block indefinitely.
An application that employs the EPOLLET flag should use nonblocking file descriptors to avoid having a blocking read or write starve a task
that is handling multiple file descriptors. The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows:
i with nonblocking file descriptors; and
ii by waiting for an event only after read(2) or write(2) return EAGAIN.(这里的EAGAIN表示缓冲区没有数据可读,或者写缓冲区已经写满了)
抛砖引玉
关于阻塞和非阻塞IO
关于边沿触发和水平触发
边沿触发为什么不能用阻塞IO
欢迎大家批评指正,共同进步
最后
以上就是魁梧红牛为你收集整理的通俗易懂描述 epoll中的边沿触发和水平触发epoll中两种触发模式介绍为什么一定要把边沿触发和非阻塞io一起使用呢解决方法抛砖引玉欢迎大家批评指正,共同进步的全部内容,希望文章能够帮你解决通俗易懂描述 epoll中的边沿触发和水平触发epoll中两种触发模式介绍为什么一定要把边沿触发和非阻塞io一起使用呢解决方法抛砖引玉欢迎大家批评指正,共同进步所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复