【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函数会收到该消息。