目录
流管理线程的创建与注册的slot 和 TmModule 对应的关系参见我的之前的一遍文章中创建非工作线程的子线程部分 参照: suricata 各个线程干的事情 -- 主线程_xuwaiwai的博客-CSDN博客
线程函数:tv->tm_func()对应的函数,TmThreadsManagement,suricata中较多的管理线程都在这个函数里执行,包括一些初始化,线程循环,线程退出。
线程的初始化
设置线程名字和绑定cpu。
注册的模块的初始化,管理线程只注册了一个slot(即 FlowManager 模块),
初始化函数为 s->SlotThreadInit 在此对应为
static TmEcode FlowRecyclerThreadInit(ThreadVars *t, const void *initdata, void **data)
函数中执行:
static TmEcode FlowRecyclerThreadInit(ThreadVars *t, const void *initdata, void **data)
{
FlowRecyclerThreadData *ftd = SCCalloc(1, sizeof(FlowRecyclerThreadData));
if (ftd == NULL)
return TM_ECODE_FAILED;
if (OutputFlowLogThreadInit(t, NULL, &ftd->output_thread_data) != TM_ECODE_OK) {
SCLogError(SC_ERR_THREAD_INIT, "initializing flow log API for thread failed");
SCFree(ftd);
return TM_ECODE_FAILED;
}
SCLogDebug("output_thread_data %p", ftd->output_thread_data);
*data = ftd;
return TM_ECODE_OK;
}
实例化一个本线程特有的结构FlowRecyclerThreadData *ftd,
初始化流日志记录器,这将为单个注册的日志程序运行线程init函数 。
状态统计数据初始化。
设置tv的flag为THV_INIT_DONE,以便主线程将此 tv->flag 的暂停标记去除。
流管理逻辑处理函数
r = s->Management(tv, SC_ATOMIC_GET(s->slot_data));
由于slot对应的是FlowManager 模块,则此函数为
static TmEcode FlowRecycler(ThreadVars *th_v, void *thread_data)
主循环
FlowRecycler函数中执行死循环
while (1)
{
...
SC_ATOMIC_ADD(flowrec_busy,1);
FlowQueuePrivate list = FlowQueueExtractPrivate(&flow_recycle_q);
const int bail = (TmThreadsCheckFlag(th_v, THV_KILL));
/* Get the time */
memset(&ts, 0, sizeof(ts));
TimeGet(&ts);
SCLogDebug("ts %" PRIdMAX "", (intmax_t)ts.tv_sec);
Flow *f;
while ((f = FlowQueuePrivateGetFromTop(&list)) != NULL) {
Recycler(th_v, ftd->output_thread_data, f);
recycled_cnt++;
}
SC_ATOMIC_SUB(flowrec_busy,1);
...
if (bail) {
break;
}
...
usleep(250);
...
}
在循环中每隔250微秒循环一次,取出flow_recycle_q中的流对流,并通过static void Recycler(ThreadVars *tv, void *output_thread_data, Flow *f) 函数回收。
static void Recycler(ThreadVars *tv, void *output_thread_data, Flow *f)
{
FLOWLOCK_WRLOCK(f);
(void)OutputFlowLog(tv, output_thread_data, f);
FlowClearMemory (f, f->protomap);
FLOWLOCK_UNLOCK(f);
FlowSparePoolReturnFlow(f);
}
函数 FlowClearMemory ,清除从回收队列中摘除的Flow的信息。
然后再调用 FowSparePoolReturnFlow 函数,将上一步已经清除信息的Flow 放入到备用队列中,这个备用队列将会在workThread中新会话获取新流时被使用。
void FlowSparePoolReturnFlow(Flow *f)
{
SCMutexLock(&flow_spare_pool_m);
if (flow_spare_pool == NULL) {
flow_spare_pool = FlowSpareGetPool();
}
DEBUG_VALIDATE_BUG_ON(flow_spare_pool == NULL);
/* if the top is full, get a new block */
if (flow_spare_pool->queue.len >= flow_spare_pool_block_size) {
FlowSparePool *p = FlowSpareGetPool();
DEBUG_VALIDATE_BUG_ON(p == NULL);
p->next = flow_spare_pool;
flow_spare_pool = p;
}
/* add to the (possibly new) top */
FlowQueuePrivateAppendFlow(&flow_spare_pool->queue, f);
flow_spare_pool_flow_cnt++;
SCMutexUnlock(&flow_spare_pool_m);
}
线程退出
执行线程退出函数,然后退出。
凡是过往,即为序章