Linux网络编程-epoll

参考

Linux网络编程(epoll函数的使用)

  • epoll机制
  • 相关函数
  • 代码示例

一、epoll函数

epoll详解(使用、原理、实验)
提供三种系统调用:

  • epoll_create():创建一个 eventpoll 对象(epoll池)
  • epoll_ctl():想epoll对象(epoll池)添加或删除所要监听的socket
  • epoll_wait():收集在epoll监控的事件中已经发生的事件

1 epoll_create()

epoll_create详解
创建一个epoll实例(epoll池)并返回该实例对应的文件描述符fd。

该文件描述符用于随后的所有对epoll的调用接口。每创建一个epoll句柄,会占用一个fd,因此当不再需要时,应使用close关闭epoll_create()返回的文件描述符,否则可能导致fd被耗尽。

#include <sys / epoll.h>
nfd = epoll_creat(max_size);

max_size:这个监听的数目最大有多大.

2. epoll_ctl()

通过指定的 epfd 参数来操作特定的 epoll 实例

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

op 参数表示操作类型

  • EPOLL_CTL_ADD:将指定的文件描述符 fd 添加到 epoll 实例中,并注册相应的事件。这样,当该文件描述符上的事件就绪时,就会通知应用程序。
  • EPOLL_CTL_MOD:修改已经注册在 epoll 实例中的文件描述符 fd 对应的事件。可以修改事件的类型、关注的事件、关联的用户数据等。
  • EPOLL_CTL_DEL:删除已经注册在 epoll 实例中的文件描述符 fd。

fd 参数是目标文件描述符,用于指定需要进行操作的文件描述符。

event 参数是一个指向 struct epoll_event 结构体的指针,用于指定事件相关的配置。

  • uint32_t events:表示注册的事件类型,可以是 EPOLLIN(可读事件)、EPOLLOUT(可写事件)、EPOLLRDHUP(对端关闭连接)、EPOLLPRI(有紧急数据可读)、EPOLLERR(错误事件)等。可以使用位掩码进行组合。
  • epoll_data_t data:用于存储用户数据信息,可以是文件描述符本身的值,也可以是用户自定义的数据结构指针。

函数的返回值为 0 表示操作成功,-1 表示出现错误,具体的错误信息可以通过检查 errno 变量获得。

3.epoll_wait()

等待监听的所有fd相应事件的产生.

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

参数说明:

  • int epfd: epoll_create()函数返回的epoll实例的句柄。
  • struct epoll_event * events: 接口的返回参数,epoll把发生的事件的集合从内核复制到 events数组中。events数组是一个用户分配好大小的数组,数组长度大于等于maxevents。(events不可以是空指针,内核只负责把数据复制到这个 events数组中,不会去帮助我们在用户态中分配内存)
  • int maxevents: 表示本次可以返回的最大事件数目,通常maxevents参数与预分配的events数组的大小是相等的
  • int timeout: 表示在没有检测到事件发生时最多等待的时间,超时时间(>=0),单位是毫秒ms,-1表示阻塞,0表示不阻塞。

返回需要处理的事件数目。失败返回0,表示等待超时。

4.epoll_event结构体

#include<sys/epoll.h>
struct epoll_event {
    uint32_t events;  	// epoll 事件类型,包括可读,可写等
    epoll_data_t data; 	// 用户数据,可以是一个指针或文件描述符等
};

events字段表示要监听的事件类型,可以是以下值之一:

  • EPOLLIN:表示对应的文件描述符上有数据可读
  • EPOLLOUT:表示对应的文件描述符上可以写入数据
  • EPOLLRDHUP:表示对端已经关闭连接,或者关闭了写操作端的写入
  • EPOLLPRI:表示有紧急数据可读
  • EPOLLERR:表示发生错误
  • EPOLLHUP:表示文件描述符被挂起
  • EPOLLET:表示将epoll设置为边缘触发模式
  • EPOLLONESHOT:表示将事件设置为一次性事件

data字段表示用户数据,它的类型是一个union,可以存放一个指针或文件描述符等数据。

typedef union epoll_data {
    void *ptr;
    int fd;
    uint32_t u32;
    uint64_t u64;
} epoll_data_t;
  • ptr可以指向任何类型的用户数据
  • fd表示文件描述符
  • u32和u64分别表示一个32位和64位的无符号整数。

使用时,用户可以将自己需要的数据存放到这个字段中,当事件触发时,epoll系统调用会返回这个数据,以便用户处理事件。

5.总结

总结来说,当某个进程调用epoll_create方法时,内核会创建一个eventpoll对象(即文件描述符epfd所代表的对象,可以通俗地称之为epoll池)。之后就可以往池子里增、删、改需要监视(感兴趣)的fd,这需要使用epoll_ctl调用。

Linux内核使用红黑树来实现管理epoll池中的fd。红黑树是一种平衡二叉树,其增删改操作时间复杂度为O ( log n ),能够保证稳定的查找性能。

二、epoll实现服务器

主要步骤

  1. 创建socket:使用socket函数创建一个监听套接字,用于接受客户端的连接请求。
  2. 绑定socket:使用bind函数将监听套接字绑定到一个特定的IP地址和端口。
  3. 监听连接:使用listen函数开始监听连接请求,指定服务器可接受的最大连接数。
  4. 创建epoll实例:使用epoll_create函数创建一个epoll实例,返回一个文件描述符。
  5. 将监听套接字添加到epoll实例:使用epoll_ctl函数将监听套接字添加到epoll实例中,并注册对读事件的关注。
  6. 进入事件循环:循环调用epoll_wait函数来等待事件的发生,该函数会阻塞当前线程直至有事件发生。一旦有事件发生,它将返回一个就绪事件的列表。
  7. 处理就绪事件:遍历就绪事件列表,对每个事件进行处理。根据事件类型,可以进行接受连接、读取数据、发送数据或关闭连接等操作。
  8. 根据需要添加或删除文件描述符:在处理完一个事件后,可以根据需要使用epoll_ctl函数动态地添加或删除文件描述符,以便继续监听其他事件。
  9. 重复步骤6-8:继续循环执行步骤6-8,处理新的就绪事件,直到服务器主动关闭或出现错误条件为止。
  • 17
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值