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

【15】Strongswan watcher详解2

watcher的核心业务函数watch:
(1)如果count为0,没有要监听的句柄,则watcher状态设置为WATCHER_STOPPED,返回,返回值为JOB_REQUEUE_NONE,这会返回到“【11】Strongswan processor 详解1”中的process_job返回处,销毁watcher job。再调用add时,再加入。
(2)watcher状态机WATCHER_QUEUED-》 WATCHER_RUNNING;
(3)使用poll机制,

struct pollfd {int fd; // 文件描述符short events; // 需要监控的事件short revents; // 实际发生的事件
};//根据监听的fd数量分配pollfd空间,此外为pipe管道的读事件也额外分配一个pfd空间。
pfd = alloca(sizeof(*pfd) * (count + 1));
//监听pipe管道的读事件
pfd[0].fd = this->notify[0];
pfd[0].events = POLLIN;//遍历pipe管道的读事件之外的所有监听fd,设置pfd
count = 1;
for (entry = this->fds; entry; entry = entry->next)
{//in_callback在notify中++,在notify_end中--,作用是已有事件没处理完(异步地processor那里没有处理完)先不再加入pfd监测,if (!entry->in_callback){pfd[count].fd = entry->fd;pfd[count].events = 0;reset_event_log(eventbuf, eventpos);if (entry->events & WATCHER_READ){log_event(eventpos, 'r');pfd[count].events |= POLLIN;}if (entry->events & WATCHER_WRITE){log_event(eventpos, 'w');pfd[count].events |= POLLOUT;}end_event_log(eventpos);log_fd(logpos, loglen, entry->fd, eventbuf);count++;}
}

(4) 调用poll

thread_cleanup_push((void*)activate_all, this);
old = thread_cancelability(TRUE);res = poll(pfd, count, -1);
if (res == -1 && errno == EINTR)
{/* LinuxThreads interrupts poll(), but does not make it a* cancellation point. Manually test if we got canceled. */thread_cancellation_point();
}thread_cancelability(old);
//参数false,压入的activate_all不执行
thread_cleanup_pop(FALSE);......
//revents 为实际发生的事件,没有发生则为空
if (pfd[0].revents & POLLIN)
{while (TRUE){//pipe O_NONBLOCK enable:当当没有数据可读时,调用返回-1,errno值为EAGAIN,跳出循环//有数据时,读到buf中, len = read(this->notify[0], buf, sizeof(buf));if (len == -1){if (errno != EAGAIN && errno != EWOULDBLOCK){DBG1(DBG_JOB, "reading watcher notify failed: %s",strerror(errno));}break;}}this->pending = FALSE;DBG2(DBG_JOB, "watcher got notification, rebuilding");break;
}......
for (entry = this->fds; entry; entry = entry->next)
{//?if (entry->in_callback){continue;}reset_event_log(eventbuf, eventpos);//返回当前entry->fd对应pfd的实际发生事件,可能为空没发生或发生,也可能是错误revents = find_revents(pfd, count, entry->fd);if (revents & POLLERR){log_event(eventpos, 'e');}if (revents & POLLIN){log_event(eventpos, 'r');}if (revents & POLLOUT){log_event(eventpos, 'w');}//fd的读事件,如socket收到了数据if (entry->events & WATCHER_READ &&revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)){//notify暂时将entry插入jobs队列,后续统一在(5)中再加入processor的job队列处理notify(this, entry, WATCHER_READ);}//fd的写事件,如socket发送数据if (entry->events & WATCHER_WRITE &&revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)){notify(this, entry, WATCHER_WRITE);}end_event_log(eventpos);log_fd(logpos, loglen, entry->fd, eventbuf);
}

notify函数:

/*** 为已注册的 FD 执行回调*/
static void notify(private_watcher_t *this, entry_t *entry,watcher_event_t event)
{notify_data_t *data;/* 获取 Async Job 的 entry 副本,但具有特定事件 */INIT(data,.entry = entry,.fd = entry->fd,.event = event,.cb = entry->cb,.data = entry->data,.keep = TRUE,.this = this,);/* deactivate entry,这样我们就可以 poll() 其他 FDs,即使异步处理还没有处理该事件 *///换句话说,processer异步处理完成该事件,再重新poll该事件entry->in_callback++;//notify_async是该事件业务的最终调用,会调用该事件的处理回调this->jobs->insert_last(this->jobs,callback_job_create_with_prio((void*)notify_async, data,(void*)notify_end, (callback_job_cancel_t)return_false,JOB_PRIO_CRITICAL));
}/*** 执行已注册 FD 的回调,异步*/
static job_requeue_t notify_async(notify_data_t *data)
{thread_cleanup_push((void*)unregister, data);data->keep = data->cb(data->data, data->fd, data->event);thread_cleanup_pop(FALSE);//只执行一次,在processor的process_job中销毁该事件对应processor里的job时会调用notify_end,见(6)return JOB_REQUEUE_NONE;
}

(5)watcher 监听fd有事件时,

if (this->jobs->get_count(this->jobs))
{while (this->jobs->remove_first(this->jobs,(void**)&job) == SUCCESS){lib->processor->execute_job(lib->processor, job);}/* we temporarily disable a notified FD, rebuild FDSET */break;
}

(6)notify_end

/*** 清理通知数据,重新激活 FD*/
static void notify_end(notify_data_t *data)
{private_watcher_t *this = data->this;entry_t *entry, *prev = NULL;watcher_event_t updated = 0;bool removed = FALSE;/* reactivate the disabled entry */this->mutex->lock(this->mutex);//遍历watcher的fds,匹配后,判断该事件业务函数的返回值(见notify_async的data->keep = data->cb(data->data, data->fd, data->event);)如果不保持则从fds中移除该事件,注意in_callback--,以便于该事件可以重新pollfor (entry = this->fds; entry; prev = entry, entry = entry->next){if (entry == data->entry){if (!data->keep){//可能的读写事件互换,这发生事件业务回调里面修改了data->event(见notify_async中的data->cb)entry->events &= ~data->event;updated = entry->events;if (!entry->events){remove_entry(this, entry, prev);removed = TRUE;break;}}entry->in_callback--;break;}}this->condvar->broadcast(this->condvar);update_and_unlock(this);if (removed){DBG3(DBG_JOB, "removed fd %d[%s%s] from watcher after callback", data->fd,data->event & WATCHER_READ ? "r" : "",data->event & WATCHER_WRITE ? "w" : "");}else if (updated){DBG3(DBG_JOB, "updated fd %d[%s%s] to %d[%s%s] after callback", data->fd,(updated | data->event) & WATCHER_READ ? "r" : "",(updated | data->event) & WATCHER_WRITE ? "w" : "", data->fd,updated & WATCHER_READ ? "r" : "",updated & WATCHER_WRITE ? "w" : "");}free(data);
}

相关文章:

【15】Strongswan watcher详解2

watcher的核心业务函数watch: (1)如果count为0,没有要监听的句柄,则watcher状态设置为WATCHER_STOPPED,返回,返回值为JOB_REQUEUE_NONE,这会返回到“【11】Strongswan processor 详解…...

linux shell编程之条件语句(二)

目录 一. 条件测试操作 1. 文件测试 2. 整数值比较 3. 字符串比较 4. 逻辑测试 二. if 条件语句 1. if 语句的结构 (1) 单分支 if 语句 (2) 双分支 if 语句 (3) 多分支 if 语句 2. if 语句应用示例 (1) 单分支 if 语句应用 (2) 双分支 if 语句应用 (3) 多分支 …...

uniapp uni-collapse动态切换数据时高度不能自适应

需单独调用方法更新 this.$nextTick(() > {if (this.$refs.collapseBox) {this.$refs.collapseBox.resize()} })...

递归?递推?

前言:递归、递推是两种非常常见基础的算法了,但我之前忘了从这基础的先讲起了,大家应该也都略有了解吧!今天突然想写点相关延伸内容,所以还是完整介绍一些吧 递归 递归是一种通过函数调用自身解决问题的算法。在递归…...

蓝桥杯--结束

冲刺题单 基础 一、简单模拟(循环数组日期进制) (一)日期模拟 知识点 1.把月份写为数组,二月默认为28天。 2.写一个判断闰年的方法,然后循环年份的时候判断并更新二月的天数 3.对于星期数的计算&#…...

【ChCore Lab 01】Bomb Lab 拆炸弹实验(ARM汇编逆向工程)

文章目录 1. 前言2. 实验代码版本问题3. 关于使用问题4. 宏观分析5. read_line 函数介绍6. phase_0 函数6.1. read_int 函数6.2. 回到 phase_0 函数继续分析6.3. 验证结果 7. phase_1 函数7.2. 验证结果 8. phase_2 函数8.1. read_8_numbers 函数8.2. 回到 phase_2 函数继续分析…...

Android-应用签名

1 需求 Android 支持以下三种应用签名方案: v1 方案:基于 JAR 签名。v2 方案:APK 签名方案 v2(在 Android 7.0 中引入)。v3 方案:APK 签名方案 v3(在 Android 9 中引入)。v4 方案&…...

二分答案----

二分答案 - 题目详情 - HydroOJ 问题描述 给定一个由n个数构成的序列a,你可以进行k次操作,每次操作可以选择一个数字,将其1,问k次操作以后,希望序列里面的最小值最大。问这个值是多少。 输入格式 第一行输入两个正…...

AI前沿周报:2025年3月技术深度解析

以下是基于2024-2025年AI技术前沿动态的深度技术周报示例,结合行业最新突破与研究进展,突出技术原理与应用场景分析: AI前沿周报:2025年3月技术深度解析 时间范围:2025年3月1日-3月31日 本期焦点:模型透明…...

Android Coil 3默认P3色域图加载/显示不出来

Android Coil 3默认P3色域图加载/显示不出来 解决&#xff0c;需要在Androidmanifest.xml使用Coil 3的activity配置属性&#xff1a; <activityandroid:colorMode"wideColorGamut"...</activity>...

Linux 系统管理常用命令

以下是 Linux 系统管理常用命令 的详细介绍&#xff0c;涵盖 IP地址查看、端口管理、进程监控 等核心操作&#xff0c;并附上实际示例&#xff1a; 一、查看网卡 IP 地址 1. 使用 ip 命令 # 查看所有网络接口信息&#xff08;包括 IP 地址&#xff09; ip addr show# 查看特定…...

Transformer多卡训练初始化分布式环境:(backend=‘nccl‘)

Transformer多卡训练初始化分布式环境:(backend=‘nccl’) dist.init_process_group(backend=nccl)在多卡环境下初始化分布式训练环境,并为每个进程分配对应的 GPU 设备。下面为你逐行解释代码的含义: 1. 初始化分布式进程组 try:dist.init_process_group(backend=nccl) e…...

Kubernetes集群环境搭建与初始化

1.Kubernetes简介&#xff1a; Kubernetes是Google开源的一个容器编排引擎&#xff0c;它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时&#xff0c;通常要部署该应用的多个实例以便对应用请求进行负载均衡。 在Kubernetes中&#xff0c;我…...

Jetson AGX Xavier开发套件使用方法

Jetson AGX Xavier是一款由NVIDIA推出的一款强大的嵌入式AI开发平台&#xff0c;适合边缘计算和目标检测任务。如果你手上有一台 Jetson AGX Xavier Developer Kit&#xff0c;就可以使用它进行明火烟雾目标检测实验。以此为例&#xff0c;为了使你能够从零开始设置设备并完成实…...

erlang的安装-linux

1&#xff1a;解压 tar -zxvf 安装包 2&#xff1a;进入解压的目录执行&#xff1a; ./configure --prefix/usr/local/erlang --with-ssl --enable-threads --enable-smp-support --enable-kernel-poll --enable-hipe --without-javac 3&#xff1a;编译安装&#xff1a; m…...

Windows 图形显示驱动开发-WDDM 1.2功能_WDDM 1.2 和 Windows 8

简介 WDDM 是随 Windows Vista 一起引入的&#xff0c;以取代 Windows XP 或 Windows 2000 显示驱动程序模型 (XDDM) 。 随着 Windows Vista 中的引入&#xff0c;WDDM 体系结构提供了启用新功能的功能&#xff0c;例如桌面组合、增强的容错、视频内存管理器、GPU 计划程序、D…...

数据可视化 —— 多边图应用(大全)

一、介绍&#xff1a; 多边形图&#xff0c;也就是在数据可视化中使用多边形来呈现数据的图表&#xff0c;在多个领域都有广泛的应用场景&#xff0c;以下为你详细介绍&#xff1a; 金融领域 投资组合分析&#xff1a;在投资组合管理中&#xff0c;多边形图可用于展示不同资…...

小张的工厂进化史——工厂模式

小张的工厂进化史——工厂模式 一、简单工厂模式&#xff1a;全能生产线二、工厂方法模式&#xff1a;分品牌代工三、抽象工厂模式&#xff1a;生态产品族四、三种模式核心对比表五、结合Spring实现简单工厂&#xff08;实践&#xff09; 小张从华强北起家&#xff0c;最初只有…...

AIP-217 不可达资源

编号217原文链接AIP-217: Unreachable resources状态批准创建日期2019-08-26更新日期2019-08-26 有时&#xff0c;用户可能会请求一系列资源&#xff0c;而其中某些资源暂时不可用。最典型的场景是跨集合读。例如用户可能请求返回多个上级位置的资源&#xff0c;但其中某个位置…...

C语言,原码、补码、反码

计算机是以补码来存储的 原码&#xff1a;正数最高位为&#xff1a;0&#xff1b;负数最高位为&#xff1a;1 &#xff08;最高位是符号位&#xff09; 正数&#xff1a;三码合一 如&#xff1a;2&#xff1a; 原码&#xff1a;0000 0000 0000 0000 0000 0000 0000 0010&#…...

2025年智能合约玩法创新白皮书:九大核心模块与收益模型重构Web3经济范式

——从国库管理到动态激励的加密生态全栈解决方案 一、核心智能合约架构解析 1. 国库合约&#xff1a;生态财政中枢 作为协议的金库守卫者&#xff0c;国库合约通过多签冷钱包与跨链资产池实现资金沉淀。其创新点包括&#xff1a; 储备资产动态再平衡&#xff1a;采用预言机实…...

【Android】Android 打包 Release 崩溃问题全解析:Lint 错误、混淆类丢失及解决方法大全

摘要&#xff1a; 在 Android 项目的 Release 打包过程中&#xff0c;经常遇到诸如 Lint 校验失败、程序闪退、类找不到等问题。本文将详细分析 Android 打包时常见的崩溃原因&#xff0c;特别是如何应对 Lint 报错、混淆引发的类丢失&#xff08;NoClassDefFoundError&#xf…...

C++ Cereal序列化库的使用

C Cereal 库使用指南 Cereal 是一个轻量级的 C 序列化库&#xff0c;用于将对象序列化为二进制、XML 或 JSON 格式&#xff0c;以及从这些格式反序列化。它支持标准库类型和用户自定义类型的序列化&#xff0c;且无需修改原有类定义。 基本用法 1. 安装与包含 #include <…...

热门面试题第15天|最大二叉树 合并二叉树 验证二叉搜索树 二叉搜索树中的搜索

654.最大二叉树 力扣题目地址(opens new window) 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下&#xff1a; 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树是通过数组中最大值右边部分构造出的最大…...

如何查看linux history命令文件

在Linux系统中&#xff0c;history命令用于显示用户在终端会话中执行过的命令历史。默认情况下&#xff0c;这些命令被保存在用户的家目录下的一个隐藏文件中&#xff0c;通常是.bash_history&#xff08;对于bash shell&#xff09;或.zsh_history&#xff08;对于zsh shell&a…...

css易混淆的知识点

子选择器 (>) vs 后代选择器 (空格) 子选择器 (>) 只匹配直接子元素。后代选择器 (空格) 匹配所有后代元素&#xff08;无论嵌套多深&#xff09;。 绝对定位vs相对定位 布局&#xff1a; justify-content 的作用 控制子元素在主轴上的分布方式。常见值包括 flex-start、…...

Java对接智能客服:从0到1构建高并发对话系统的实战指南

引言&#xff1a;智能客服的进化与Java生态的融合 在数字化转型浪潮中&#xff0c;智能客服系统已成为企业服务升级的标配。当传统规则引擎逐步让位于NLP大模型&#xff0c;Java开发者如何构建高效稳定的对话系统&#xff1f;本文将结合阿里云通义千问、百度文心等最新AI能力&…...

【前缀和】矩阵区域和(medium)

矩阵区域和&#xff08;medium&#xff09; 题⽬描述&#xff1a;解法&#xff1a;代码Java 算法代码&#xff1a;C 算法代码&#xff1a; 题⽬描述&#xff1a; 题⽬链接&#xff1a;1314. 矩阵区域和 给你⼀个 m x n 的矩阵 mat 和⼀个整数 k &#xff0c;请你返回⼀个矩阵 …...

5分钟用Docker Desktop新功能搭建Python+AI开发环境

Docker Desktop 4.25版本通过预置AI开发模板与零配置GPU支持&#xff0c;彻底简化PythonAI环境搭建流程。无需手动安装CUDA、无需配置虚拟环境&#xff0c;3条命令完成从零到模型训练的完整工作流。 一、Docker Desktop新功能核心价值 1.1 预置AI开发镜像库 • 开箱即用的深度…...

一周学会Pandas2 Python数据处理与分析-Pandas2读取Excel

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili Excel格式文件是办公使用和处理最多的文件格式之一&#xff0c;相比CSV文件&#xff0c;Excel是有样式的。Pandas2提…...