网络编程: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 :超时时间到达,却没有事件返回时

相关推荐
未济3 天前
linux 配置环境变量
linux
傲世仙尊3 天前
目录即文件-Ext文件系统收尾篇
linux·c语言
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
_艾伦 耶格尔.3 天前
进程间通信
linux
Liuqy-053 天前
Linux IO编程——静态库、动态库
linux
wuyk5553 天前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网
彧azz3 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
-梅3 天前
linux(8) 软硬链接
linux·运维·服务器
Wang's Blog3 天前
Java 项目实战: 外卖平台-文件下载与ServletOutputStream回写浏览器
服务器·项目开发
AIgorithmGEEK3 天前
[Linux]线程三部曲(上):一个执行流的诞生——从操作系统一路拆到 pthread_create
linux·线程·pid