网络编程:IO多路复用(select、poll、epoll)

  1. 创建文件描述符集合

  2. 将关注的文件描述符添加到集合

  3. 将文件描述符传递给内核,内核开始检测IO事件

  4. 内核返回到达事件的结果

select:

特点:

  1. 使用数组(位图)保存文件描述符集合,最多允许监测1024个文件描述符;

  2. 将集合表创建在应用层,存在应用层和内核层数据的反复拷贝;

  3. 事件到达时,内核返回整个集合表,应用层需要遍历;

  4. select只能工作在水平触发模式(低速模式),不能工作在边沿触发模式(高速模式);

  5. 创建文件描述符集合(位图(数组)--》1024)

fd_set fds;

FD_ZERO(&fds);

  1. 将要监测的文件描述符加入集合

FD_SET(fd, &fds);

  1. 将集合传递给内核开始监测IO事件,并且返回监测的结果

int select(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds, struct timeval *timeout);

功能:将文件描述符传递给内核开始监测IO事件,并返回监测到的结果

参数:

nfds:监测的文件描述符最大值+1

readfds:要监测的读事件的文件描述符集合

writefds:要监测的写事件的文件描述符集合

exceptfds:要监测的出错事件的文件描述符集合

timeout:超时时间

NULL :不设置超时时间:阻塞等到

返回值:

成功:实际到达的IO事件的个数

失败:-1

0 :设置超时事件,超时时间到没有事件到达

void FD_CLR(int fd, fd_set *set);

int FD_ISSET(int fd, fd_set *set);

void FD_SET(int fd, fd_set *set);

void FD_ZERO(fd_set *set);

cpp 复制代码
int sockfd = socket();
bind();
listen();
//sockfd-->rdfds
while (1)
{
    select(rdfds);
    if (FD_ISSET(sockfd))
    {
    int connfd = accept();
        //connfd --->rdfds
    }
    for (i = sockfd+1; i <= maxfd; ++i)
    {
        if (FD_ISSET(i))
        {
            recv();
            send();
        }
    }
}

poll:
特点:

  1. 使用链表保存文件描述符集合,允许监测的文件描述符没有上限限制;

  2. 创建的文件描述符集合在应用层,需要应用层和内核层的反复数据拷贝;

  3. 应用层对于返回的事件结果需要遍历查找;

  4. poll只能工作在水平触发模式(低速模式),无法工作在边沿触发模式(高速模式)。

epoll:

特点:

  1. 使用树形结构(红黑树)保存文件描述符集合,没有文件描述符上限限制,并且查找效率高;

  2. 文件描述符集合创建在内核层,避免了应用层和内核层的反复数据拷贝;

  3. 直接返回到达事件的文件描述符集合;

  4. epoll可以工作在水平触发模式(低速模式),也可以工作在边沿触发模式(高速模式);

1. 创建文件描述符集合

int epoll_create(int size);

功能:创建epoll的文件描述符集合

参数:

size :允许监测的文件描述符的个数

返回值:

成功:返回文件描述符句柄。

失败:-1

2. 添加文件描述符到集合

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

功能:对文件描述符集合中的文件描述符做操作

参数:

epfd:epoll创建的文件描述符集合

op:操作方法:

EPOLL_CTL_ADD :添加操作

EPOLL_CTL_MOD :修改操作

EPOLL_CTL_DEL :删除操作

fd :要操作的文件描述符

event:epoll事件结构体

typedef union epoll_data {

void *ptr;

int fd; //要监测的文件描述符

uint32_t u32;

uint64_t u64;

} epoll_data_t;

struct epoll_event {

uint32_t events; /* Epoll events */

epoll_data_t data; /* User data variable */

};

events:事件类型

EPOLLIN: 读事件

EPOLLOUT :写事件

返回值:

成功:0

失败:-1

3. 通知内核开始监测事件

int epoll_wait(int epfd, struct epoll_event *events,

int maxevents, int timeout);

功能:通知内核开始监测事件

参数:

epfd:监测的文件描述符句柄

events :保存epoll返回的到达事件的集合

maxevents:最多监测的事件个数

timeout:设置超时时间

-1 :不设置超时,一直阻塞等待

返回值:

成功:实际到达的事件的个数

失败:-1

0 :超时时间到达,却没有事件返回时

相关推荐
数字智核34 分钟前
2026昆山工厂空压机突然停机怎么办?找谁抢修
服务器·网络·数据库
迷路爸爸18036 分钟前
在 Ubuntu / Linux 上轻量安装 LaTeX:TinyTeX 使用记录
linux·运维·ubuntu
pt104344 分钟前
网络自动化Python课程:利用Cisco NSO编排网络服务
运维·网络·自动化
tedcloud1231 小时前
OpenLogi 怎么搭建?用 Rust 打造一个轻量的 Logitech 外设管理工具
linux·运维·服务器·开发语言·后端·rust·开源
AAA代码批发商1 小时前
Days 39 Linux C 开发之 SQLite 数据库完整学习笔记
linux·c语言·数据库
Wang's Blog2 小时前
Vibe Coding一人即团队系列54:云服务器 Node.js 与 MySQL 9 环境搭建及配置指南
服务器·人工智能·mysql·node.js
额额额对了2 小时前
Linux 数据库开发实战:使用 C 语言与 SQLite3 构建轻量级终端词典
linux·数据库·oracle
爱笑鱼2 小时前
Android 系统启动机制(六):Zygote 创建 App 为什么走 Socket?哪些是源码事实,哪些是架构解释?
android·linux
全栈技术负责人2 小时前
DeepSeek Harness 业务工具权限插件 dsh-tool-permission设计思路
网络·算法·ai·ai编程