Linux高阶IO 2

1 篇文章 0 订阅
1 篇文章 0 订阅

上篇
Linux高阶IO 1

epoll的优缺点
优点缺点
描述符无上限相较于select多路转接模型无法跨平台
每个事件只需要向内核拷贝一次
epoll在内核使用事件回调将就绪事件添加到双向链表,每过一段时间epoll就会查看双向链表是否为空借此来判断是否有描述符就绪,并且不会随着描述符的增多而使内核性能降低
epoll直接将就绪的事件拷贝到用户态,这样使得用户得到的事件直接就是就绪状态的,用户可以直接进行操作,而且它与select不同的是不用从集合中去判断到底是哪一个事件准备就绪
多路转接模型的适用场景
  • 应用于大量连接,但是同一时间只有少量连接活跃的场景,因为多路转接是并发处理请求的
epoll的惊群问题
何为惊群?
  • 惊群现象:就是多个进程或者线程同时阻塞等待某一事件的发生,若是这个事件发生了,就会唤醒所有在等待其发生的进程\线程,但是这个事件只能被一个进程\线程处理,而其他的进程\线程只能报错返回继续休眠,这样就会造成性能资源浪费。我们把这种现象称之为惊群。
  • 模型
父进程的Socket
fork
等待接收
fork
等待接收
fork
等待接收
fork
等待接收
父进程
socket
worker子进程
accept
worker子进程
accept
worker子进程
accept
worker子进程
accept
  • 对于进程与线程的惊群问题,在Linux2.4版本之后就解决了。解决的方式(当多个进程\线程等待客户连接时,当一个客户发起连接请求,内核接收到这个请求之后,将不会唤醒多个进程\线程而只是唤醒等待队列上的第一进程或者线程。 所以采用accept阻塞调用方式在Linux上已经没有惊群现象了)
    但是对于线程或者进程中使用多路转接模型(select,poll,epoll),引起的惊群问题只是部分解决,当进程\线程中使用多路转接模型epoll在epoll_wait 之后调用sleep一次就会出现惊群问题。
解决方案
  • 使用mutex互斥锁解决这个问题,具体使用全局互斥锁,每当一个子进程\线程在epoll_wait()之前先申请锁,申请到后才能继续处理,获取不到等待。并且设置一个均衡算法(当一个进程的任务量接近最大时,他将不会尝试去申请锁),由此均衡各个进程之间的任务量。具体的需要看Nginx的惊群处理

  • 参考网站:

  • epoll惊群问题

  • accept与epoll惊群

边缘触发/水平触发
  • 边缘触发:
    每一条新的数据到来偶会触发就绪事件,(不管缓冲区的数据是否大于低水位标记)

  • 水平触发:
    只要缓冲区数据大于低水位标记,就会触发就绪事件

  • epoll有两种触发模式可选,默认是水平触发;但是select只有水平触发模式。
    一旦epoll的触发模式被设为边缘触发,将要求用户每次都将缓冲区中的数据读完进行处理(不触发就就绪,那么socket按照程序逻辑就不会多次处理)(并且一旦这样做了,必须一次将数据读完,因为读不完的数据将会触发数据补全,这种状况可能无法处理,但是要一次读完的话就要多读几次,但是多读几次就有可能会阻塞,但是 在并发模型中不能存在阻塞情况,因此需要将描述符设置为非阻塞状态 )。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值