Linux 系统 epoll 函数解析

Linux 系统 epoll 函数解析

linux的epoll函数被我们许多程序,框架大量的使用,如java 的NIO,netty, nginx,dubbo,rocketMQ等,

epoll 底层3个函数

我们先来了解下epoll底层的3个函数是干什么,然后在分析其原理

  • epoll_create(int size)

    epoll_create()会在内存中开辟一块空间,用来存放epoll中fd(文件描述符,即socket连接)的数据结构,参数size并不是限制了epoll所能监听的描述符最大个数,只是对内核初始分配内部数据结构的一个建议

  • epoll_ctl

    epoll_ctl()会把每一个socket的fd数据结构放到epoll_create()创建内存空间

  • epoll_wait

    只有当epoll_create()中创建的内存空间中的fd有事件发生,才会把这些fd放到就绪链表中(封装了有事件发生的socket链表),并返回就绪链表的个数

理解上面3个函数的作用很重要,上面3个函数互相配合才构成了liunx的epoll,下面我们来看看一段C语言代码

在这里插入图片描述

上面这段代码很好的模拟了客户端连接服务端的过程,注意epoll_create, epoll_ctl, epoll_wait的调用,详情看注释

事件通知机制

linux 底层是通过事件通知机制实现的,过程如下

  1. 我们客户端发送数据,会先达到服务器的网卡,网卡会把该数据放到DMA(内存中的一个buffer,网卡可以直接访问这个数据区域)中
  2. 网卡把数据放到内存后,会向cpu发起中断,让cpu先处理网卡的数据
  3. 中断号在内存中会绑定一个回调,哪个socket中有数据,回调函数就把哪个socket放入就绪链表中(唤醒epoll_wait),表示有事件发生,
  4. 然后linux内核线程就会遍历该事件链表,处理相关事件(如:读写数据)

epoll总结和Nio,Redis, Nginx等调用

epoll是现在最先进的IO多路复用器,Redis、Nginx,linux中的Java NIO都使用的是epoll。
这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。

  1. 一个socket的生命周期中只有一次从用户态拷贝到内核态的过程,开销小
  2. 使用event事件通知机制,每次socket中有数据会主动通知内核,并加入到就绪链表中,不需要遍历所有的socket
  • 在多路复用IO模型中,会有一个内核线程不断地去轮询多个 socket 的状态,只有当真正读写事件发送时,才真正调用实际的IO读写操作。
  • 因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有真正有读写事件进行时,才会使用IO资源,所以它大大减少来资源占用。
  • 多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
  • 采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),

Nio,Redis, Nginx的底层都采用调用epoll函数来实现高效的网络读写,具体过程如下:

  1. 当服务器启动时候,先调用epoll_create方法,开辟一块内存空间,用来存放socket连接

  2. 当客户端建立连接时,会调用 epoll_ctl 函数 把socket连接放到epoll_create开辟的内存空间中

  3. 当客户端向服务端写数据的时候,会通知内核有写事件,内核就会发生事件的socket放到就绪链表中,此时epoll_wait就调用了。

  4. 然后linux内核线程就会遍历该就绪链表,处理相关的读写事件

  5. 上面的epoll操作都是发生在linux内核中的,速度会非常快

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值