当前位置: 首页 > article >正文

ngx_epoll_add_event

1 定义ngx_epoll_add_event 函数 定义在 ./nginx-1.24.0/src/event/modules/ngx_epoll_module.cstaticngx_int_tngx_epoll_add_event(ngx_event_t*ev,ngx_int_tevent,ngx_uint_tflags){intop;uint32_tevents,prev;ngx_event_t*e;ngx_connection_t*c;structepoll_eventee;cev-data;events(uint32_t)event;if(eventNGX_READ_EVENT){ec-write;prevEPOLLOUT;#if(NGX_READ_EVENT!EPOLLIN|EPOLLRDHUP)eventsEPOLLIN|EPOLLRDHUP;#endif}else{ec-read;prevEPOLLIN|EPOLLRDHUP;#if(NGX_WRITE_EVENT!EPOLLOUT)eventsEPOLLOUT;#endif}if(e-active){opEPOLL_CTL_MOD;events|prev;}else{opEPOLL_CTL_ADD;}#if(NGX_HAVE_EPOLLEXCLUSIVENGX_HAVE_EPOLLRDHUP)if(flagsNGX_EXCLUSIVE_EVENT){events~EPOLLRDHUP;}#endifee.eventsevents|(uint32_t)flags;ee.data.ptr(void*)((uintptr_t)c|ev-instance);ngx_log_debug3(NGX_LOG_DEBUG_EVENT,ev-log,0,epoll add event: fd:%d op:%d ev:%08XD,c-fd,op,ee.events);if(epoll_ctl(ep,op,c-fd,ee)-1){ngx_log_error(NGX_LOG_ALERT,ev-log,ngx_errno,epoll_ctl(%d, %d) failed,op,c-fd);returnNGX_ERROR;}ev-active1;#if0ev-oneshot(flagsNGX_ONESHOT_EVENT)?1:0;#endifreturnNGX_OK;}ngx_epoll_add_event 函数的作用是 负责将 NGINX 的读或写事件注册到 Linux epoll 实例中。 它根据事件类型构造对应的 epoll 监听掩码读:EPOLLIN|EPOLLRDHUP写:EPOLLOUT 并自动判断应该向 epoll 添加新 fd 还是修改已有事件 若同一连接的另一事件已活跃则合并事件掩码进行修改避免覆盖 最后通过 epoll_ctl 完成操作使连接的事件得以被异步监控。2 详解1 函数签名staticngx_int_tngx_epoll_add_event(ngx_event_t*ev,ngx_int_tevent,ngx_uint_tflags)返回值 成功返回 NGX_OK值为 0 失败返回 NGX_ERROR值为 -1参数1 ngx_event_t *ev 指向 ngx_event_t 结构的指针 是本次要注册监听的事件参数2 ngx_int_t event 事件类型 指明当前要注册的是读事件还是写事件NGX_READ_EVENT监听可读事件对应 EPOLLIN | EPOLLRDHUP NGX_WRITE_EVENT监听可写事件对应 EPOLLOUT参数3 ngx_uint_t flags 用来控制 epoll 行为的 控制标志 多个标志可通过按位或 | 组合传入2 逻辑流程1 局部变量 2 获取连接对象 3 事件配置 4 epoll_ctl 注册事件监听 5 返回成功1 局部变量{intop;uint32_tevents,prev;ngx_event_t*e;ngx_connection_t*c;structepoll_eventee;2 获取连接对象cev-data;从事件对象中取出连接指针。 Nginx 中每个事件ngx_event_t的 data 字段都指向其所属的 ngx_connection_t 结构 这样可以通过事件快速访问连接的所有信息3 事件配置events(uint32_t)event;初始化目标事件掩码。 将调用方传入的 Nginx 抽象事件常量强转为 32 位无符号整型。 作为初始值后续会根据实际情况做 位运算if(eventNGX_READ_EVENT){ec-write;prevEPOLLOUT;#if(NGX_READ_EVENT!EPOLLIN|EPOLLRDHUP)eventsEPOLLIN|EPOLLRDHUP;#endif}else{ec-read;prevEPOLLIN|EPOLLRDHUP;#if(NGX_WRITE_EVENT!EPOLLOUT)eventsEPOLLOUT;#endif}#1-1 判断要操作的事件是否为读事件 若为读事件则将对立事件指针 e 指向连接的写事件。 这是因为在一个连接上读写事件是成对存在的 当添加读事件时需要关心写事件当前是否已经注册以便做修改还是添加的决定 #1-2 如果写事件已经活跃那么它在 epoll 中监听的标志通常是 EPOLLOUT可写。 这里预设 prev 为 EPOLLOUT当执行 EPOLL_CTL_MOD 时 将会通过 events | prev 把写事件标志合并进去从而不会丢失写事件的监听。 #1-3 这是条件编译 如果宏 NGX_READ_EVENT 的值不等于 EPOLLIN|EPOLLRDHUP 则把 events 设置为这两个标志的位或。 该条件编译通常为真因为 Nginx 定义的 NGX_READ_EVENT 往往是一个简单的枚举值如 0 与真正的 epoll 位掩码不同。所以这里就是正确设置了读事件的监听集合。 EPOLLIN 数据可读包括正常数据和优先带数据。 EPOLLRDHUP 对端关闭连接或仅关闭写半部半关闭 这是 Linux 2.6.17 引入的标志允许应用区分对端完全关闭和只关闭写。#2-1 否则即 event 为 NGX_WRITE_EVENT处理写事件 对于写事件对立事件是连接的读事件因此 e 指向读事件 #2-2 如果读事件已经活跃则它监听的标志通常是 EPOLLIN|EPOLLRDHUP。 这里设定 prev 为这个组合以便在修改模式下保留读事件的监听。 #2-3 条件编译 如果 NGX_WRITE_EVENT 宏的值不等于 EPOLLOUT 则将 events 设为 EPOLLOUT可写。 这也是常见情况因为写事件枚举值通常不与 EPOLLOUT 直接相等。if(e-active){opEPOLL_CTL_MOD;events|prev;}else{opEPOLL_CTL_ADD;}#1 检查对立事件是否已经处于活跃状态即是否已被 epoll 监控。 e-active 标志会在事件成功通过 epoll_ctl 添加/修改后被置为 1。 若对立事件活跃说明该连接对应的文件描述符fd已经在 epoll 中被监听 epoll 是以 fd 为索引的一个 fd 只能被添加一次后续都需要修改。 因此本次操作必须是 修改EPOLL_CTL_MOD不能是添加。 设置操作码为 EPOLL_CTL_MOD表示修改已存在 fd 的监听事件 把对立事件的原有监听标志prev合并到当前要设置的 events 中。 因为 epoll 修改事件时新的事件掩码会完全覆盖原来的掩码 所以必须显式把另一方向的事件重新包含进去否则另一方向的监听就会丢失。#2 对立事件不活跃说明该 fd 是第一次注册事件或者之前的事件已被删除因而执行添加操作 操作码设为 EPOLL_CTL_ADD将 fd 首次加入 epoll 监听列表#if(NGX_HAVE_EPOLLEXCLUSIVENGX_HAVE_EPOLLRDHUP)if(flagsNGX_EXCLUSIVE_EVENT){events~EPOLLRDHUP;}#endif这是一个条件编译块 只有在系统支持 EPOLLEXCLUSIVE 并且也支持 EPOLLRDHUP 时才会编译。 EPOLLEXCLUSIVE 是 Linux 4.5 引入的标志 用于多进程/多线程共享同一个监听 socket 时 以独占方式唤醒等待队列中的进程避免惊群效应thundering herd。 然而在某些内核实现上 EPOLLEXCLUSIVE 与 EPOLLRDHUP 一起使用可能会有问题例如某些场景下破坏独占语义或造成未定义行为。因此 Nginx 在这里主动清除 EPOLLRDHUP 标志。 如果调用传入了 NGX_EXCLUSIVE_EVENT 标志 则执行 events ~EPOLLRDHUP从事件掩码中去掉 EPOLLRDHUP 位。ee.eventsevents|(uint32_t)flags;ee.data.ptr(void*)((uintptr_t)c|ev-instance);ngx_log_debug3(NGX_LOG_DEBUG_EVENT,ev-log,0,epoll add event: fd:%d op:%d ev:%08XD,c-fd,op,ee.events);#1 构建最终传递给 epoll_ctl 的事件标志。 将前面得到的 events例如 EPOLLIN|EPOLLOUT|EPOLLRDHUP 与传入的 flags可能包含 EPOLLET、EPOLLONESHOT、EPOLLEXCLUSIVE 等做位或 得到完整的 epoll 事件掩码。 注意 flags 的类型是 ngx_uint_t这里显式转换为 uint32_t 以匹配 ee.events 的类型#2 设置 epoll 事件携带的用户数据 ee.data.ptr 是 void *通常用来存放事件相关的上下文指针。 Nginx 将连接指针 c 与事件的 instance 标志做位或存入 ptr。 原因c 是一个指针其地址由于内存对齐至少 4 或 8 字节对齐而最低若干位始终为 0。 ev-instance 是一个 0 或 1 的整数用来标识事件是否过期。 当 epoll 触发事件时Nginx 会取出 ptr通过隔离低位得到原来的连接指针(c ptr ~1) 同时通过最低位判断 instance 是否与当前事件记录的 instance 一致 从而识别并丢弃旧事件例如连接已关闭但残留的事件。 这样的位复用避免了额外内存开销是一种精巧的设计#3 输出调试日志4 epoll_ctl 注册事件监听if(epoll_ctl(ep,op,c-fd,ee)-1){ngx_log_error(NGX_LOG_ALERT,ev-log,ngx_errno,epoll_ctl(%d, %d) failed,op,c-fd);returnNGX_ERROR;}调用 Linux 系统调用 epoll_ctl对全局 epoll 实例 ep该模块内的全局变量执行 op 操作 修改 fd c-fd 的监听事件为 ee 所描述的内容。 返回值 -1 表示调用失败。ev-active1;#if0ev-oneshot(flagsNGX_ONESHOT_EVENT)?1:0;#endif将当前事件的 active 标志置为 1表示该事件现在已被 epoll 成功监听。 这个标志会在将来移除事件或事件处理时被清除同时上面的逻辑也依靠它来判断对立事件的状态5 返回成功returnNGX_OK;}

相关文章:

ngx_epoll_add_event

1 定义 ngx_epoll_add_event 函数 定义在 ./nginx-1.24.0/src/event/modules/ngx_epoll_module.cstatic ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) { int op;uint32_t events, prev;ngx_event_t …...

小升初英语衔接轻创业,KISSABC 落地全拆解

小升初英语衔接是一个家长付费意愿强、决策周期相对较短的细分市场。小学高年级家长对孩子的英语水平有清醒认知,知道初中英语和小学英语的难度差距,愿意为有效的衔接方案买单。对于想切入教育赛道的创业者来说,锁定这个群体是一个需求明确、…...

海康威视访客系统API避坑指南:从权限下发失败到动态二维码生成的5个常见问题

海康威视访客系统API实战避坑手册:5个高频故障的诊断与修复 对接海康iSC平台访客系统时,一线工程师常会遇到各种"诡异"问题:明明调用了接口却权限不下发、动态二维码生成后扫码无效、访客刷脸始终无法开门。这些问题往往消耗大量排…...

SpringMVC5.0

Spring留言板实现预期结果可以发布并显示点击提交后,显示并清除输入框并且再次刷新后,不会清除下面的缓存约定前后端交互接口Ⅰ 发布留言 url : /message/publish . param(参数) : from,to,say . return : true / false .Ⅱ 查询留言 url : /message/get…...

第四章-09-练习案例:有几个偶数

1.题目2.代码# 09-练习案例:有几个偶数 cnt 0 for i in range(1,100) :if i % 2 0 :cnt 1print(cnt)...

AD9850/AD9851模块PCB设计要点与STM32驱动实战:从原理图到可调信号发生器

1. AD9850/AD9851模块核心原理与选型指南 第一次接触DDS信号发生器时,我被AD9850芯片的精度震撼到了——用STM32驱动这个小模块,竟然能输出0.0291Hz分辨率的信号。这相当于在125MHz的时钟基准下,实现了比普通晶振高数百万倍的频率控制精度。A…...

机器学习中强弱学习器的原理与实践应用

1. 集成学习中的强弱学习器解析在机器学习领域,我们经常听到"强学习器"和"弱学习器"这两个术语。作为从业十多年的数据科学家,我发现很多初学者对这些概念的理解停留在表面。今天,我将从实践角度深入剖析这对核心概念&am…...

CUDA 13.0与Jetson Thor平台:边缘计算新纪元

1. CUDA 13.0与Jetson Thor平台概览NVIDIA最新发布的CUDA 13.0工具包为Jetson Thor SoC带来了革命性的升级,这标志着边缘计算和嵌入式GPU开发进入了一个新纪元。作为一名长期从事GPU加速开发的工程师,我认为这次更新最令人振奋的是它彻底改变了Arm生态系…...

互联网大厂 Java 求职面试:音视频场景中的技术问答

互联网大厂 Java 求职面试:音视频场景中的技术问答 在这篇文章中,我们将模拟一场互联网大厂的 Java 求职面试,场景设定为音视频领域,面试官是一位严肃的技术专家,而候选人燕双非则是一位搞笑的程序员。通过三轮的问答&…...

GBDT概率模型在空气污染预测中的应用实践

1. 项目背景与核心价值空气污染预测一直是环境科学和公共健康领域的重要课题。传统预测方法往往只能给出确定性结果,而概率预测模型则能提供更丰富的风险信息。这个项目构建的概率预测模型,能够量化未来出现污染天气的可能性,为决策者提供更科…...

【空管供配电】通过指导材料看空管供配电整体解决方案——空管STS方案

第一篇空管供电方案跳转链接(点这里) 第二篇空管UPS方案跳转链接(点这里) STS三大隐藏要求:空管供电安全的关键细节 STS(静态转换开关)是空管供电系统实现"不间断"切换的核心设备&…...

Switch手柄连接PC的终极指南:用BetterJoy实现完美适配

Switch手柄连接PC的终极指南:用BetterJoy实现完美适配 【免费下载链接】BetterJoy Allows the Nintendo Switch Pro Controller, Joycons and SNES controller to be used with CEMU, Citra, Dolphin, Yuzu and as generic XInput 项目地址: https://gitcode.com/…...

解决Windows窗口调试难题的WinSpy++实战指南:高级窗口探查与属性修改技术深度解析

解决Windows窗口调试难题的WinSpy实战指南:高级窗口探查与属性修改技术深度解析 【免费下载链接】winspy WinSpy 项目地址: https://gitcode.com/gh_mirrors/wi/winspy Windows窗口调试是桌面应用开发中的常见挑战,开发者经常面临窗口属性获取困…...

数据结构初涉----顺序表

有了我们之前共同学习的C做基础,我们本文开始学习数据结构,本文先从数据结构的基础-----顺序表开始介绍。顺序表的出现顺序表的基层原理其实就是数组,但是数组用来存放数据可以,遇到插入数据,删除数据这些操作时&#…...

PatchTST论文精读与复现:手把手带你理解‘时间序列的64个词’

PatchTST论文精读与复现:手把手带你理解"时间序列的64个词" 当Transformer架构在NLP和CV领域大放异彩时,时间序列预测领域却长期被传统统计方法和浅层神经网络主导。直到2023年PatchTST的出现,才真正打破了这一僵局。这篇来自顶级学…...

JS逆向之某招标采购平台接口aesKey、epcos以及响应content解密

文章目录 声明 一、起因与目标 二、第一步:先证明它不是普通接口 三、第二步:观察页面结构,判断从哪里下手 四、第三步:优先打请求拦截器,不要先钻业务页 1. GET 请求加密逻辑 2. POST 请求加密逻辑 五、第四步:把真正的加密函数剥出来 1. 请求加密函数 2. 响应解密函数 …...

【进程间通信】————匿名管道、模拟实现进程池

目录 1. 进程间通信 1.1 进程间通信的目的 1.2 进程间通信分类 2. 管道 3. 匿名管道 3.1 pipe函数 3.2 用 fork 来共享管道原理 3.3 从文件描述符角度理解 3.4 从内核角度理解 3.5 父子进程管道读写测试 3.6 管道特性 3.7 4种通信情况 3.8 管道的原子性 4. 进程…...

云服务器配置远程桌面

租赁云服务器通常没有图形化界面,因为想跑仿真看场景所以希望通过远程桌面的方式链接过去,那就需要服务器有图形化界面 1.安装图形化界面 ssh建立连接后 sudo apt update 极简版 sudo apt install --no-install-recommends task-gnome-desktop 简化…...

C++:模板精讲

泛型编程 当我们实现一个交换函数&#xff0c;想要实现不同类型的交换&#xff0c;可以使用函数重载&#xff1a; #include<iostream>using namespace std;void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(char& …...

015-016 类中方法中的this,解决类中this指向问题

类中方法中的this<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-wid…...

Weka回归分析实战:从数据预处理到模型部署

1. 项目概述&#xff1a;Weka中的回归机器学习实战指南在数据科学领域&#xff0c;回归分析是预测连续型变量的经典方法。Weka作为一款开源的机器学习工作台&#xff0c;以其友好的图形界面和丰富的算法库&#xff0c;成为许多从业者快速验证模型的首选工具。不同于Python/R需要…...

边缘节点的PHP应用部署、数据同步、算力调度标准化方案=hyperf最

针对边缘节点场景&#xff0c;按三个维度给你整理最实用的 Hyperf 方案&#xff1a;---一、应用部署标准化 容器化 & 打包 …...

ARM智能卡接口(SCI)架构与通信协议详解

1. ARM智能卡接口(SCI)核心架构解析 智能卡接口(Smart Card Interface, SCI)作为嵌入式系统中实现安全通信的关键模块&#xff0c;其硬件架构设计直接决定了系统与智能卡之间的通信效率和可靠性。ARM架构下的SCI模块采用分层设计理念&#xff0c;主要由物理层、协议层和应用层组…...

别再手动算了!用Matlab的dec2hex/dec2bin函数搞定进制转换(附硬件寄存器操作实例)

别再手动算了&#xff01;用Matlab的dec2hex/dec2bin函数搞定进制转换&#xff08;附硬件寄存器操作实例&#xff09; 在嵌入式开发和数字电路设计中&#xff0c;进制转换是工程师们每天都要面对的"家常便饭"。想象一下这样的场景&#xff1a;你正在调试一块FPGA板卡…...

evolver部署教程:构建自动优化AI系统

在运行进化算法或自动优化类 AI 系统时&#xff0c;计算资源与运行稳定性会直接影响结果质量。尤其是在需要长时间迭代、批量实验或多轮计算的场景中&#xff0c;一些具备稳定资源与弹性能力的环境&#xff08;如莱卡云服务器这类部署方式&#xff09;通常更有利于实验持续推进…...

扩展拖垮VSCode?禁用这3类高危插件,启动速度提升3.2倍,实测有效

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;扩展拖垮VSCode&#xff1f;禁用这3类高危插件&#xff0c;启动速度提升3.2倍&#xff0c;实测有效 VSCode 启动缓慢常被误认为是硬件或系统问题&#xff0c;但真实瓶颈往往藏在插件生态中。我们对 127…...

如果openKylin 2.0 SP2主机的IPv4地址改变,如何让GitLab正常运行

作者&#xff1a;沈传越 明德融创工作室&#xff08;Minter Fusion Studio, MFS&#xff09; 出品 本文介绍的所有步骤均经过测试复现。 本文针对GitLab管理员使用。如果对于相关的专业词汇不太清楚。可以参考以下文章&#xff1a; 《如何在openKylin下安装并配置GitLab&…...

VSCode量子插件配置踩坑实录:92%开发者忽略的3项核心环境校验与自动修复方案

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;VSCode量子插件配置踩坑实录&#xff1a;92%开发者忽略的3项核心环境校验与自动修复方案 VSCode 量子开发插件&#xff08;如 Q# Extension、Quantum Development Kit&#xff09;在启用时频繁报错&…...

DimOS:AI原生机器人操作系统入门与实践指南

1. 项目概述&#xff1a;重新定义机器人操作系统如果你在过去几年里折腾过机器人开发&#xff0c;大概率绕不开ROS&#xff08;Robot Operating System&#xff09;。从ROS 1到ROS 2&#xff0c;它确实为机器人软件模块化、通信标准化立下了汗马功劳。但说实话&#xff0c;有多…...

告别STC-ISP!手把手教你写一个通吃STC89/12/15系列单片机的延时函数库

告别STC-ISP&#xff01;手把手教你打造跨代STC51单片机的延时函数库 当你在深夜调试STC89C52RC时&#xff0c;突然接到需求要移植代码到STC15W4K32S4上&#xff0c;却发现原本精准的延时函数完全失效——这种场景对51单片机开发者来说再熟悉不过。不同指令集架构带来的时钟周期…...