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

本文讨论了在使用Linuxepoll模型的LT水平触发模式时,如何避免因socket可写事件不断触发而造成的频繁操作。提出了两种方法,一种是反复添加和删除fd,另一种是当返回EAGAIN时才将fd加入epoll管理,以减少操作。作者还提供了改进的send函数示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjq++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值