libnids中多线程

可以通过设置全局变量nids_params.multiproc不为0来在libnids中使用多线程捕获数据包。libnids使用的是glib库的gthread-2.0线程函数(该函数库某些函数已经过时,例如线程创建函数;过时的api:https://developer.gnome.org/glib/stable/glib-Deprecated-Thread-APIs.html;新版thread接口:https://developer.gnome.org/glib/stable/glib-Threads.html)。

在libnids1.24源文件libnids.c中nids_run会调用pcap_loop函数进行循环捕获数据包的操作;pcap_loop函数的回调函数nids_pcap_heandler在设置了全局变量multiproc时,会将捕获的数据包片段插入到异步捕获队列中(这里的异步队列是glib的接口,用于在不同线程之间通信,https://developer.gnome.org/glib/stable/glib-Asynchronous-Queues.html

int nids_run()
{
    if (!desc) {
	strcpy(nids_errbuf, "Libnids not initialized");
	return 0;
    }
    START_CAP_QUEUE_PROCESS_THREAD(); /* threading... */
    pcap_loop(desc, -1, (pcap_handler) nids_pcap_handler, 0); //循环捕获数据包
    /* FIXME: will this code ever be called? Don't think so - mcree */
    STOP_CAP_QUEUE_PROCESS_THREAD(); 
    nids_exit();
    return 0;
}
nids_pcap_handler部分代码:

 #ifdef HAVE_LIBGTHREAD_2_0
     if(nids_params.multiproc) {  //如果系统有thread_2_0函数库并设置了使用多线程
        /* 
         * Insert received fragment into the async capture queue.
         * We hope that the overhead of memcpy 
         * will be saturated by the benefits of SMP - mcree
         */
        qitem=malloc(sizeof(struct cap_queue_item));
        if (qitem && (qitem->data=malloc(hdr->caplen - nids_linkoffset))) {
          qitem->caplen=hdr->caplen - nids_linkoffset;
          memcpy(qitem->data,data_aligned,qitem->caplen);
          g_async_queue_lock(cap_queue);  //为异步队列加锁
          /* ensure queue does not overflow,如果队列长度大于全局变量queue_limit的限制就说明overflow了*/
          if(g_async_queue_length_unlocked(cap_queue) > nids_params.queue_limit) {
	    /* queue limit reached: drop packet - should we notify user via syslog? */
	    free(qitem->data); //丢弃数据包数据
	    free(qitem);  //销毁数据包
	    } else {
	    /* insert packet to queue */
	    g_async_queue_push_unlocked(cap_queue,qitem);
          }
          g_async_queue_unlock(cap_queue); //解锁异步队列
	}
     } else { /* user requested simple passthru - no threading */
        call_ip_frag_procs(data_aligned,hdr->caplen - nids_linkoffset);
     }
 #else
     call_ip_frag_procs(data_aligned,hdr->caplen - nids_linkoffset);
 #endif
}


可以看出nids_run函数中是通过宏START_CAP_QUEUE_PROCESS_THREAD()来创建新线程的,通过STOP_CAP_QUEUE_PROCESS_THREAD()来销毁线程的。

如下是宏 START_CAP_QUEUE_PROCESS_THREAD()和STOP_CAP_QUEUE_PROCESS_THREAD()的定义:

//g_thread_create_full从version 2.32开始被废弃了 and should not be used in newly-written code.
//https://developer.gnome.org/glib/stable/glib-Deprecated-Thread-APIs.html#g-thread-create-full

#define START_CAP_QUEUE_PROCESS_THREAD() \
    if(nids_params.multiproc) { /* threading... */ \
	 if(!(g_thread_create_full((GThreadFunc)cap_queue_process_thread,NULL,0,FALSE,TRUE,G_THREAD_PRIORITY_LOW,&gerror))) { \
	    strcpy(nids_errbuf, "thread: "); \
	    strncat(nids_errbuf, gerror->message, sizeof(nids_errbuf) - 8); \
	    return 0; \
	 }; \
    }

#define STOP_CAP_QUEUE_PROCESS_THREAD() \
    if(nids_params.multiproc) { /* stop the capture process thread */ \
	 g_async_queue_push(cap_queue,&EOF_item); \
    }
g_thread_create_full创建新线程,其中第一个参数cap_queue_process_thread是要在新创建的线程里执行的函数,它的定义如下:
/* thread entry point 
 * pops capture queue items and feeds them to
 * the ip fragment processors - mcree
 */
static void cap_queue_process_thread()
{
     struct cap_queue_item *qitem;
     
     while(1) { /* loop "forever" */
	  qitem=g_async_queue_pop(cap_queue);
	  if (qitem==&EOF_item) break; /* EOF item received: we should exit */
	  call_ip_frag_procs(qitem->data,qitem->caplen);
	  free(qitem->data);
	  free(qitem);
     }
     g_thread_exit(NULL);
}
该函数从异步队列中不断取出pcap_loop捕获的数据包,交给call_ip_frag_procs函数进行处理。上面nids_pcap_handler函数的部分代码中可以看出,如果没有设置使用多线程,那么直接在nids_pcap_handler函数中就使用call_ip_frag_procs函数处理数据包了。接下来处理过程参考 http://blog.csdn.net/u013074465/article/details/45555837

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值