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

【14】Strongswan watcher详解1

//watcher 状态
enum watcher_state_t {
	/** 没有 watcher 线程正在运行或排队 */
	WATCHER_STOPPED = 0,
	/** job已排队等待监视,但尚未启动 */
	WATCHER_QUEUED,
	/**观察程序线程处于活动状态,正在调度套接字事件 */
	WATCHER_RUNNING,
};

/**
 * 使用 poll() 监视多个文件描述符。
 */
struct watcher_t {

	/**
	 * 开始监视新的文件描述符。
	 *
	 * 可以为同一个文件描述符注册多个回调,并且所有回调都会收到通知。此类回调是并发执行的。
	 *
	 * @param fd		file descriptor to start watching
	 * @param events	ORed set of events to watch
	 * @param cb		callback function to invoke on events
	 * @param data		data to pass to cb()
	 */
	void (*add)(watcher_t *this, int fd, watcher_event_t events,
				watcher_cb_t cb, void *data);

	/**
	 * 停止监视以前注册的文件描述符。
	 *
	 * 此调用将阻塞,直到此 FD 的任何活动回调返回。为该 FD 注册的所有回调都将被取消注册。
	 *
	 * @param fd		file descriptor to stop watching
	 */
	void (*remove)(watcher_t *this, int fd);

	/**
	 * 获取当前观察程序状态
	 *
	 * @return			currently active watcher state
	 */
	watcher_state_t (*get_state)(watcher_t *this);

	/**
	 * 销毁 watcher_t。
	 */
	void (*destroy)(watcher_t *this);
};
struct private_watcher_t {
	watcher_t public;

	/**
	 * 注册的FDs句柄链表
	 */
	entry_t *fds;

	/**
	 * 最后注册的一个 FD
	 */
	entry_t *last;

	/**
	 * 注册的 FDs数量
	 */
	u_int count;

	/**
	 * 等待 FD 列表的更新?
	 */
	bool pending;

	/**
	 * watcher状态
	 */
	watcher_state_t state;

	/**
	 *  FD 链表操作互斥锁
	 */
	mutex_t *mutex;

	/**
	 * 条件变量发出回调完成信号
	 */
	condvar_t *condvar;

	/**
	 * 通知管道到信号watcher观察程序线程
	 */
	int notify[2];

	/**
	 * watcher程序线程要处理的回调job列表,如 job_t
	 */
	linked_list_t *jobs;
};
struct entry_t {
	//要watch的文件描述符
	int fd;
	//watch的事件类型读或写
	watcher_event_t events;
	//回调函数
	watcher_cb_t cb;
	//回调函数参数
	void *data;
	//回调函数是否正在执行
	int in_callback;
	//链表
	entry_t *next;
};
/**
 * 我们为异步通知传递的数据
 */
typedef struct {
	/** 正在处理的entry */
	entry_t *entry;
	/** 文件描述符 */
	int fd;
	/** 事件类型 */
	watcher_event_t event;
	/** 事件回调 */
	watcher_cb_t cb;
	/** 回调函数参数 */
	void *data;
	/** keep registered? */
	bool keep;
	/** 引用的watcher*/
	private_watcher_t *this;
} notify_data_t;

watcher_create函数
(1)创建一个private_watcher_t 实例,状态机为WATCHER_STOPPED;
(2)create_notify创建非阻塞pipe管道,this->notify;
destroy函数是反向操作

add操作:
(1)初始化一个entry,保存watch的fd,监听的事件类型,事件相关的回调及参数。
(2)将entry,也即要监听的fd事件,如读事件加入到watcher的fds链表和last链表中统一处理。同时记录entry总数。
(3)watcher状态机:WATCHER_STOPPED-》WATCHER_QUEUED,将watcher job以最高的优先级加入processor的job队列。watcher job的处理函数为watch,processor会从线程池中获取一个线程执行watcher job的watch函数,该线程是private_watcher_t 实例的运转线程。如果状态机不是WATCHER_STOPPED,则调用update_and_unlock函数,向管道写入’u’消息。处理watcher job的线程执行的watch函数会收到该消息。
remove_操作:
(1)遍历fds链表,entry->fd == fd比较,如果找到,is_in_callback = TRUE;说明正在执行,则不执行移除,this->condvar->wait(this->condvar, this->mutex) 调用remove的线程进入条件等待状态; (notify_end和activate_all函数会发信号),唤醒后重新执行(1);
(2)否则从fds链表和last链表中移除这个监听fd事件,并调用update_and_unlock函数,向管道写入’u’消息。处理watcher job的线程执行的watch函数会收到该消息。

相关文章:

  • P8682 [蓝桥杯 2019 省 B] 等差数列
  • 【C++刷题】二叉树基础OJ题
  • 基于PySide6与pyCATIA的工程图智能文本替换工具开发指南
  • OJ 基础 | 输入处理
  • SDP(一)
  • 鸿蒙HarmonyOS埋点SDK,ClkLog适配鸿蒙埋点分析
  • 深入浅出Redis 缓存使用问题 | 长文分享
  • DeepSeek 教我LLVM(2) : MCTargetDesc 核心模块有哪些?
  • [蓝桥杯]小tips
  • DevOps与功能安全:Perforce ALM通过ISO 26262合规认证,简化安全关键系统开发流程
  • 磁盘存储下红黑树、B 树与 B + 树的原理、操作及对比
  • vue3实现页面端的自适应布局
  • 解决 vite.config.ts 引入scss 预处理报错
  • java学习笔记16——java8的其他新特性
  • 遇到git提交报错:413
  • Nginx常用工具
  • cs224w课程学习笔记-第10课
  • Linux系统使用lshw生成硬件报告方法
  • 循环神经网络 - LSTM 网络的各种变体
  • Go语言中的垃圾回收是如何工作的?
  • 做泥网站/百度知道网页入口
  • 珠海做网站/网络营销课程总结1500字
  • 企业网站建设 制作/网址查询入口
  • 用织梦做网站费用/百度指数查询手机版
  • 无忧中英繁企业网站系统 破解/百度怎么推广自己的作品
  • 网站建设需要的材料/廊坊关键词快速排名