RT-DETR:可以满足实时性要求的DETR模型

rt,detr,可以,满足,实时性,要求,模型 · 浏览次数 : 34

小编点评

**epoll简介** epoll是一种 Linux 网络编程核心工具,用于创建和管理网络事件,如读写、连接和通知。它可以用于构建高效、可扩展和稳定的网络应用,提供出色的用户体验。 **epoll的特点** * **事件处理机制:**epoll使用事件处理机制,当网络事件发生时,内核会触发事件处理机制,处理相关事件。 * **非阻塞模式:**epoll支持非阻塞模式,可以同时处理多个网络事件。 * **事件缓存:**epoll可以缓存网络事件,减少事件处理的延迟。 * **高效通信:**epoll可以优化网络通信,减少发送和接收数据的延迟。 **epoll的使用注意事项** * **事件缓存大小:**事件缓存大小应该根据网络情况进行调整,例如,在网络拥塞时,可以使用更大的缓存。 * **事件处理机制:**事件处理机制应该与内核的事件处理机制一致。 * **非阻塞模式:**非阻塞模式的设置应该与应用程序的需要进行一致。 * **缓存机制:**缓存机制的设置应该与应用程序的需要进行一致。 **epoll的优越性** * **高效网络通信:**epoll可以优化网络通信,减少发送和接收数据的延迟。 * **非阻塞模式:**epoll支持非阻塞模式,可以同时处理多个网络事件。 * **事件缓存:**epoll可以缓存网络事件,减少事件处理的延迟。 * **高效通信:**epoll可以优化网络通信,减少发送和接收数据的延迟。 **epoll的缺点** * **事件处理机制:**事件处理机制可能阻塞,导致应用程序无法处理网络事件。 * **非阻塞模式:**非阻塞模式的设置可能与应用程序的需要进行不一致。 * **缓存机制:**缓存机制的设置可能与应用程序的需要进行不一致。

正文

本文分享自华为云社区《高性能网络设计秘笈:深入剖析Linux网络IO与epoll》,作者: Lion Long 。

一、epoll简介

epoll是Linux内核中一种可扩展的IO事件处理机制,可替代select和poll的系统调用。处理百万级并发访问性能更佳。

二、select的局限性

(1) 文件描述符越多,性能越差。 单个进程中能够监视的文件描述符存在最大的数量,默认是1024(在linux内核头文件中定义有 #define _FD_SETSIZE 1024),当然也可以修改,但是文件描述符数量越多,性能越差。

(2)开销巨大 ,select需要复制大量的句柄数据结构,产生了巨大的开销(内核/用户空间内存拷贝问题)。

(3)select需要遍历整个句柄数组才能知道哪些句柄有事件。

(4)如果没有完成对一个已经就绪的文件描述符的IO操作,那么每次调用select还是会将这些文件描述符通知进程,即水平触发。

(5)poll使用链表保存监视的文件描述符,虽然没有了监视文件数量的限制,但是其他缺点依旧存在。

由于以上缺点,基于select模型的服务器程序,要达到十万以上的并发访问,是很难完成的。因此,epoll出场了。

三、epoll的优点

(1)不需要轮询所有的文件描述符

(2)每次取就绪集合,都在固定位置

(3)事件的就绪和IO触发可以异步解耦

四、epoll函数原型

4.1、epoll_create(int size)

#include <sys/epoll.h>

int epoll_create(int size);

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

参数说明:size表示内核需要监控的最大数量,但是这个参数内核已经不会用到,只要传入一个大于0的值即可。 当size<=0时,会直接返回不可用,这是历史原因保留下来的,最早的epoll_create是需要定义一次性就绪的最大数量;后来使用了链表以便便维护和扩展,就不再需要使用传入的参数。

返回:返回该对象的描述符,注意要使用 close 关闭该描述符。

4.2、epoll_ctl

#include <sys/epoll.h>

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

// epoll_ctl对应系统调用sys_epoll_ctl

功能:操作epoll的文件描述符,主要是对epoll的红黑树节点进行操作,比如节点的增删改查。

参数说明:

cke_16778.png

4.2.1、event参数说明

struct epoll_event结构体原型

typedef union epoll_data{

void* ptr;

int fd;

uint32_t u32;

uint64_t u64

};

struct epoll_event{

uint32_t events;

epoll_data_t data;

}

events成员代表要监听的epoll事件类型

events成员:

cke_34833.png

data成员:

data 成员时一个联合体类型,可以在调用 epoll_ctl 给 fd 添加/修改描述符监听的事件时携带一些数据,方便后面的epoll_wait可以取出信息使用。

4.2.2、扩展说明:SYSCALL_DEFINE数字 的宏定义

跟着的数字代表函数需要的参数数量,比如SYSCALL_DEFINE1代表函数需要一个参数、SYSCALL_DEFINE4代表函数需要4个参数。

4.2.3、注意

epoll_ctl是非阻塞的,不会被挂起。

4.3、epoll_wait

函数原型

#include <sys/epoll.h>

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

功能:阻塞一段时间,等待事件发生

返回:返回事件数量,事件集添加到events数组中。也就是遍历红黑树中的双向链表,把双向链表中的节点数据拷贝出来,拷贝完毕后把节点从双向链表中移除。

cke_50950.png

五、epoll使用步骤

step 1:创建epoll文件描述符

int epfd = epoll_create(1);

step 2:创建struct epoll_event结构体

struct epoll_event ev;

ev.data.fd=listenfd;//保存监听的fd,以便epoll_wait的后续操作

ev.events=EPOLLIN;//设置监听fd的可读事件

step 3:添加事件监听

epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);

step 4:等待事件

struct epoll_event events[EVENTS_LENGTH];

char rbuffer[MAX_BUFF]={ 0 };

char wbuffer[MAX_BUFF]={ 0 };

while(1)

{

int nready = epoll_wait(epfd,events,EVENTS_LENGTH,-1);//-1表示阻塞等待

int i=0;

for(i=0;i<nready;i++)

{

int clientfd=events[i].data.fd;

if(clientfd==listenfd)

{

struct sockaddr_in client;

int len=sizeof(client);

int confd=accept(listenfd,(struct sockaddr*)&client,&len);

//step 2:创建struct epoll_event结构体

struct epoll_event evt;

evt.data.fd=confd;//保存监听的fd,以便epoll_wait的后续操作

evt.events=EPOLLIN;//设置监听fd的可读事件

// step 3:添加事件监听

epoll_ctl(epfd,EPOLL_CTL_ADD,confd,&evt);

}

else if(events[i].events &EPOLLIN)

{

int ret = recv(clientfd,rbuffer,MAX_BUFF,0);

if(ret>0)

{

rbuffer[ret]='\0';//剔除干扰数据

printf("recv: %s\n",rbuffer);

memcpy(wbuffer,rbuffer,MAX_BUFF);//拷贝数据,做回传示例

//step 2:创建struct epoll_event结构体

struct epoll_event evt;

evt.data.fd=clientfd;//保存监听的fd,以便epoll_wait的后续操作

evt.events=EPOLLOUT;//设置监听fd的可写事件

// step 3:修改事件监听

epoll_ctl(epfd,EPOLL_CTL_MOD,clientfd,&evt);

}

}

else if(events[i].events &EPOLLOUT)

{

int ret = send(clientfd,wbuffer,MAX_BUFF,0);

printf("send: %s\n",wbuffer);

//step 2:创建struct epoll_event结构体

struct epoll_event evt;

evt.data.fd=clientfd;//保存监听的fd,以便epoll_wait的后续操作

evt.events=EPOLLIN;//设置监听fd的可读事件

// step 3:修改事件监听

epoll_ctl(epfd,EPOLL_CTL_MOD,clientfd,&evt);



}

}

}

六、完整示例代码

#include <stdio.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <fcntl.h>

#include <unistd.h>

#include <pthread.h>

#include <sys/epoll.h>

#include <string.h>

#define BUFFER_LENGTH 128

#define EVENTS_LENGTH 128

char rbuff[BUFFER_LENGTH] = { 0 };

char wbuff[BUFFER_LENGTH] = { 0 };

int main() {

// block

int listenfd = socket(AF_INET, SOCK_STREAM, 0); //

if (listenfd == -1) return -1;

// listenfd

struct sockaddr_in servaddr;

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

servaddr.sin_port = htons(9999);

if (-1 == bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) {

return -2;

}

#if 0 // nonblock

int flag = fcntl(listenfd, F_GETFL, 0);

flag |= O_NONBLOCK;

fcntl(listenfd, F_SETFL, flag);

#endif

listen(listenfd, 10);

int epfd = epoll_create(1);

struct epoll_event ev, events[EVENTS_LENGTH];

ev.events = EPOLLIN;

ev.data.fd = listenfd;

epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);

printf("epfd : %d\n", epfd);

while (1)

{

int nready = epoll_wait(epfd, events, EVENTS_LENGTH, -1);

printf("nready --> %d\n",nready);

int i;

for (i = 0; i < nready;i++)

{

int clientfd = events[i].data.fd;

if (listenfd == clientfd)

{

// accept

struct sockaddr_in client;

int len = sizeof(client);

int conffd = accept(clientfd, (struct sockaddr*)&client,&len);

printf("conffd --> %d\n",conffd);

ev.events = EPOLLIN;

ev.data.fd = conffd;

epoll_ctl(epfd, EPOLL_CTL_ADD, conffd, &ev);

}

else if(events[i].events & EPOLLIN)//client

{

int ret=recv(clientfd, rbuff, BUFFER_LENGTH, 0);

if (ret > 0)

{

rbuff[ret] = '\0';

printf("recv buffer: %s\n", rbuff);

/*

int j;

for (j = 0; j < BUFFER_LENGTH;j++)

{

buff[j] = 'a' + (j % 26);

}

send(clientfd, buff, BUFFER_LENGTH, 0);

*/

memcpy(wbuff, rbuff, BUFFER_LENGTH);

ev.events = EPOLLOUT;

ev.data.fd = clientfd;

epoll_ctl(epfd, EPOLL_CTL_MOD, clientfd, &ev);

}



}

else if (events[i].events & EPOLLOUT)

{

send(clientfd, wbuff, BUFFER_LENGTH, 0);

printf("send --> %s\n",wbuff);

ev.events = EPOLLIN;

ev.data.fd = clientfd;

epoll_ctl(epfd, EPOLL_CTL_MOD, clientfd, &ev);

}

}

}



return 0;

}

七、epoll的缺点

读写使用相同的缓冲区。比如上述的示例中,wbuffer和rbuffer是使用同一个缓冲区的,所以需要rbuff[ret] = ‘\0’;去除杂数据。

八、水平触发(LT)与边沿触发(ET)

8.1、两者差异

1、水平触发可以一次recv,边沿触发需要用循环来recv;

2、水平触发可以使用阻塞模式,边沿模式不能

3、两者性能差异非常小,一般小数据使用水平触发LT,大数据使用边沿触发ET

4、listen fd最好使用水平触发,尽量不要边沿触发

5、当当recv的buffer小于接受的数据时:

(1)水平触发是只要有数据就一直触发,直到数据读完;

(2)边沿触发是来一次连接触发一次,如果接受数据的buffer不够大,则数据会保留在缓冲区,下次触发继续从缓冲区读出来;

6、一般,水平触发只需要一个recv,边沿触发需要搭配while从缓冲区读完数据

8.2、设置触发模式

默认是水平触发模式,在事件中设置中 | EPOLLET 就可以设置边沿触发,不设置则默认是水平触发。

例如:

ev.events=EPOLL_IN | EPOLLET

九、常见疑惑问题

9.1、为什么提前先定义一个事件?

我们需要注册,内核才会有事件来的时候通知进程。比如生活中要退一个快递,那么我们需要注册一个快递公司的账户,然后发送一个退快递请求时快递公司才能找到你并取快递。

9.2、epoll events超出EVENTS_LENGTH?

epoll会循环拷贝红黑树结构体中的双向链表节点,读取节点数据,直到没有事件。

9.3、缓冲区有多大空间时才返回可读/可写?

只要缓冲区有空间就返回可读、可写,不管空间多少。比如缓冲区是1024,但是有1023有数据了,这种极端条件也会返回可读、可写。

9.4、recv和send放在一起时,有什么问题?

发送给客户端数据很大的时候(大于内核缓冲区),就可能出现send不全,客户端recv不全,最好用EPOLLOUT单独处理发送数据事件。

总结

本文介绍了网络IO模型,引入了epoll作为Linux系统中高性能网络编程的核心工具。通过分析epoll的特点与优势,并给出使用epoll的注意事项和实践技巧,该文章为读者提供了宝贵的指导。通过掌握这些知识,读者能够构建高效、可扩展和稳定的网络应用,提供出色的用户体验。

 

点击关注,第一时间了解华为云新鲜技术~

 

与RT-DETR:可以满足实时性要求的DETR模型相似的内容:

RT-DETR:可以满足实时性要求的DETR模型

近年来,基于Transformer的端到端目标检测器越来越受到学术界的关注和研究。然而DETR复杂的计算量导致它很难在实际应用中落地,因此本文提出了第一个满足实时性要求的DETR模型RT-DETR

mirai Bot初始化配置

RT 其实本来我的bot已经因为自己手贱登陆qq nt直接报废了,但是论坛里有佬提供了新的协议库,那这不赶紧复活bot都对不起这个新的协议库。 本文写于2024年7月4日19:20:21,可能随着时间久远而无法实现功能。 由于存在下载障碍,所以这里也搞了个存档,本帖中的相关标星*资源无法下载均可以从

RT-Thread Studio使用教程

介绍 RT-Thread Studio是官方出品的一款专门针对RT-Thread嵌入式开发、部署、调试、测试的集成开发环境,它基于Eclipse开源项目开发,极大的提高了嵌入式开发者的开发效率,目前最新版本是2.26 下载 使用浏览器打开RT-Thread官网,选择左上角资源点击RT-Thread

rt下降40%?程序并行优化六步法

并行优化在改善程序接口响应时间和吞吐量指标方面是个利器,所以本次结合前段时间做的一段长链路执行逻辑代码的优化,给大家讲讲程序并行优化的步骤及方法论。

STM32 + RT-Thread + LVGL

一、基本信息 MCU:STM32F103ZET6 RT-Thread:5.0.2 LVGL:8.3.11 LCD:ST7735s 编译环境:RTThread studio 二、LVGL 移植要求 16、32或64位微控制器或处理器 建议速度大于16 MHz 闪存/ROM: > 64 kB(建议180

HMI-Board上手指南

介绍 HMI-Board为 RT-Thread 联合瑞萨推出的高性价比图形评估套件,取代传统的 HMI+主控板硬件,一套硬件即可实现 HMI+IoT+控制的全套能力。依托于瑞萨高性能芯片 RA6M3 及 RT-Thread 软件生态,HMI-Board 不仅硬件性能强劲,同时软件生态丰富,助力开发者

[转帖]QPS、TPS、RT、并发量、 吞吐量

QPS 每秒查询率(QPS,Queries-per-second)是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。 每秒查询率(QPS,Queries-per-second)是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每

[转帖]三分钟读懂BGP中RD与RT

https://www.jianshu.com/p/4da7997d1f90 Route-Distinguisher(后简称"RD"), Route-Target(后简称"RT")经常出现在EVPN、MPLS VPN中,但它们是完全不同的两个概念,初学者往往难以区分两者的差异。学霸题:区分"RT""

[转帖]QPS、TPS、RT、并发数、吞吐量理解和性能优化深入思考

https://baijiahao.baidu.com/s?id=1675704570461446033&wfr=spider&for=pc 吞吐量 在了解qps、tps、rt、并发数之前,首先我们应该明确一个系统的吞吐量到底代表什么含义,一般来说,系统吞吐量指的是系统的抗压、负载能力,代表一个系统

一个简单的科普-延迟与RT时间

# 一个简单的科普-延迟与RT时间 ## 背景 ``` 发现稍微一复杂就没人看. 这次像是写一个简单的科普文章. 主要说一下网络延迟还有网络的响应时间. 这里想通过一个题目进行引申. 如果Skylink全球商用: 中国与美国之间的网络是走海底光纤延迟低,还是走skylink延迟低? ``` ## 关