LT模式下epoll一直通知可写怎么办?

简介: LT模式下epoll一直通知可写怎么办?

使用Linux epoll模型的LT水平触发模式,当socket可写时,会不停的触发socket可写的事件,如何处理?

-----网络流传的腾讯面试题

方法一:每一次需要写入时,将fd加入epoll,轮询到可写并写完数据后,将fd移除epoll管理

既然当socket可写时,会不停触发事件,那么从一开始就将需要写入的fd不加入epoll的EPOLLOUT事件中,当需要写入的时候,再加入epoll管理,轮询fd可写,数据全部写完后,将fd移除epoll管理,避免反复通知

这种方法需要反复添加和删除

方法二:需要写入时,直接调用send或write,当返回错误码EAGAIN时,才将fd加入epoll管理,等待fd可写后写入数据,写入完成后,将fd移出epoll

改进的做法相当于认为socket在大部分时候是可写的,不能写了再让epoll帮忙监控

鄙人根据方法二写的send函数:

int epoll_LT_send(int fd, char *buf, int length) {
    int ret = send(fd, buf, length, 0); // 需要写入时,直接调用send
    if (ret < 0) { // 当返回错误码EAGAIN时,才将fd加入epoll管理
        if(errno == EAGAIN || errno == EWOULDBLOCK) { 
            int epfd = epoll_create(1);
            if (epfd == -1) {
                perror("epoll_create");
                return -1;
            }
            
            struct epoll_event ev;
            ev.data.fd = fd;
            ev.events = EPOLLOUT;
    // 将fd加入epoll管理
            if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) { 
                perror("epoll_ctl");
                close(epfd);
                return -1;
            }
            ret = 0;
            while(1) { // 等待fd可写后写入数据
                struct epoll_event events;
                int nready = epoll_wait(epfd, &events, 1, -1);
                if (nready == -1) {
                    perror("epoll_wait");
                    close(epfd);
                    return -1;
                } else if (nready == 0) {
                    continue;
                }
            
                do { // 写入数据
                    int r = send(fd, buf+ret, (length - ret), 0);
                    if (r > 0) {
                    ret += r;
                    } else if (r == -1) {
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
                            close(epfd);
                            return ret;
                        } else {
                            perror("send");
                            close(epfd);
                            return -1;
                        }
                    }
                
                } while (ret < length);
                break;
            } 
    // 写入完成后,将fd移出epoll
        epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
        }
    return ret;
        
    } else if (ret == 0) { // disconnect
        perror("send");
        return -1;
    }
    
return ret;
}

推荐学习 https://xxetb.xetslk.com/s/p5Ibb

目录
相关文章
|
Prometheus 监控 Cloud Native
【云原生】Docker容器命令监控+Prometheus监控平台
【云原生】Docker容器命令监控+Prometheus监控平台
696 0
【云原生】Docker容器命令监控+Prometheus监控平台
|
存储 缓存 NoSQL
Redis过期Key的清理机制
Redis过期Key的清理机制
303 1
|
缓存 监控 数据挖掘
C# 一分钟浅谈:性能测试与压力测试
【10月更文挑战第20天】本文介绍了性能测试和压力测试的基础概念、目的、方法及常见问题与解决策略。性能测试关注系统在正常条件下的响应时间和资源利用率,而压力测试则在超出正常条件的情况下测试系统的极限和潜在瓶颈。文章通过具体的C#代码示例,详细探讨了忽视预热阶段、不合理测试数据和缺乏详细监控等常见问题及其解决方案,并提供了如何避免这些问题的建议。
289 7
|
Ubuntu 应用服务中间件 nginx
Ubuntu安装笔记(三):ffmpeg(3.2.16)源码编译opencv(3.4.0)
本文是关于Ubuntu系统中使用ffmpeg 3.2.16源码编译OpenCV 3.4.0的安装笔记,包括安装ffmpeg、编译OpenCV、卸载OpenCV以及常见报错处理。
843 2
Ubuntu安装笔记(三):ffmpeg(3.2.16)源码编译opencv(3.4.0)
|
测试技术 Python
|
中间件 开发者
史上最详细的Gin中间件使用教程
1.概述 Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。
1513 89
史上最详细的Gin中间件使用教程
|
前端开发 安全 Java
如何在Java中实现高效率的文件上传和下载
如何在Java中实现高效率的文件上传和下载
|
缓存 并行计算 Ubuntu
在Ubuntu系统下部署大语言模型
在Ubuntu系统下部署大语言模型
841 0
|
安全 C++
c++ 无锁队列的简单实现
c++ 无锁队列的简单实现
728 0
|
消息中间件 存储 安全
zeromq无锁队列的原理与实现
zeromq无锁队列的原理与实现
371 0