Clamav杀毒软件源码分析笔记[七]

  Clamav杀毒软件源码分析笔记[七]


刺猬@http://blog.csdn.net/littlehedgehog





[accept循环处理]


上次本来可以在文章五把Clamd的主要函数说完的,不过线程未了,火候未到. 这次火候到了,Clamd的尽头也就走到底了.


  1.     if ((thr_pool=thrmgr_new(max_threads, idletimeout, scanner_thread)) == NULL)
  2.     {
  3.         logg("!thrmgr_new failed/n");
  4.         exit(-1);
  5.     }
  6.     time(&start_time);      //记录当前时间 保存在start_time中 
  7.     for (;;)
  8.     {   
  9.         new_sd = accept(socketd, NULL, NULL);
  10.         
  11.         /* 注意啦注意啦 中断也会打断accept阻塞 这里我们只需要检查errno是不是EINTR即可 如果返回值为-1(表示accpet失败)
  12.          * 又不是中断打扰所致,那就是出了其他问题了.
  13.          */
  14.         if ((new_sd == -1) && (errno != EINTR))     
  15.         {
  16.             /* very bad - need to exit or restart */
  17. #ifdef HAVE_STRERROR_R
  18.             logg("!accept() failed: %s/n", strerror_r(errno, buff, BUFFSIZE));
  19. #else
  20.             logg("!accept() failed/n");
  21. #endif
  22.             continue;
  23.         }
  24.         
  25.         /* 此信号一出 表示终端断线了 我们需要重新打开log文件*/
  26.         if (sighup)
  27.         {
  28.             logg("SIGHUP caught: re-opening log file./n");
  29.             logg_close();
  30.             sighup = 0;
  31.             if (!logg_file && (cpt = cfgopt(copt, "LogFile")))
  32.                 logg_file = cpt->strarg;
  33.         }
  34.         
  35.         /*  progexit是我们进程收到了SIGINT相关信号设置的标识 如果收到很不幸,我们要退出了 */
  36.         if (!progexit && new_sd >= 0)
  37.         {
  38.             client_conn = (client_conn_t *) mmalloc(sizeof(struct client_conn_tag));        //这里是组装thrmgr_dispatch的userdata参数 
  39.             client_conn->sd = new_sd;       //socket 描述符! 后面老是要用到 这个是服务端和客户端通信的一个通道 
  40.             client_conn->options = options;
  41.             client_conn->copt = copt;
  42.             client_conn->root = cl_dup(root);
  43.             client_conn->root_timestamp = reloaded_time;
  44.             client_conn->limits = &limits;
  45.             client_conn->mainpid = mainpid;
  46.             if (!thrmgr_dispatch(thr_pool, client_conn))
  47.             {
  48.                 close(client_conn->sd);
  49.                 free(client_conn);
  50.                 logg("!thread dispatch failed/n");
  51.             }
  52.         }
  53.         pthread_mutex_lock(&exit_mutex);
  54.         if (progexit)
  55.         {
  56.             if (new_sd >= 0)
  57.             {
  58.                 close(new_sd);
  59.             }
  60.             pthread_mutex_unlock(&exit_mutex);
  61.             break;
  62.         }
  63.         pthread_mutex_unlock(&exit_mutex);
  64.         
  65.         //如果设置了自我检查
  66.         if (selfchk)
  67.         {
  68.             time(&current_time);
  69.             if ((current_time - start_time) > (time_t)selfchk)      //这里是指病毒库的时间超过了我们设置的有效时间    
  70.             {
  71.                 if (reload_db(root, copt, TRUE))        //这个是检测数据库是否已经被更改,若是要设置reload 方便下面重新加载点
  72.                 {
  73.                     pthread_mutex_lock(&reload_mutex);
  74.                     reload = 1;
  75.                     pthread_mutex_unlock(&reload_mutex);
  76.                 }
  77.                 time(&start_time);
  78.             }
  79.         }
  80.         pthread_mutex_lock(&reload_mutex);
  81.         if (reload)
  82.         {
  83.             pthread_mutex_unlock(&reload_mutex);
  84.             root = reload_db(root, copt, FALSE);
  85.             pthread_mutex_lock(&reload_mutex);
  86.             reload = 0;
  87.             time(&reloaded_time);
  88.             pthread_mutex_unlock(&reload_mutex);
  89. #ifdef CLAMUKO
  90.             if (cfgopt(copt, "ClamukoScanOnLine") || cfgopt(copt, "ClamukoScanOnAccess"))
  91.             {
  92.                 logg("Stopping and restarting Clamuko./n");
  93.                 pthread_kill(clamuko_pid, SIGUSR1);
  94.                 pthread_join(clamuko_pid, NULL);
  95.                 tharg->root = root;
  96.                 pthread_create(&clamuko_pid, &clamuko_attr, clamukoth, tharg);
  97.             }
  98. #endif
  99.         }
  100.         else
  101.         {
  102.             pthread_mutex_unlock(&reload_mutex);
  103.         }
  104.     }
  105.     /* Destroy the thread manager.
  106.      * This waits for all current tasks to end
  107.      */
  108.     thrmgr_destroy(thr_pool);

这里一定要贴出  if ((thr_pool=thrmgr_new(max_threads, idletimeout, scanner_thread)) == NULL)

主要是想说在创建线程池的时候我们就已经确定好了线程执行的函数 scanner_thread 大家可以回头看看线程池创建处理代码. 下面就是给线程组装参数结构体了,主要是线程传参数形式已被定死了,所以我们要装载结构体.



线程的处理函数也只是一个代理而已,真正办实事的干部只有command了.如下所示:


  1. /* 线程的主函数 在这里面设置处理job */
  2. void scanner_thread(void *arg)
  3. {
  4.     client_conn_t *conn = (client_conn_t *) arg;
  5.     sigset_t sigset;
  6.     int ret, timeout, session=FALSE;
  7.     struct cfgstruct *cpt;
  8.     /* ignore all signals 这里作者已经注释了,这里全设置为1,其实是屏蔽信号 */
  9.     sigfillset(&sigset);
  10.     pthread_sigmask(SIG_SETMASK, &sigset, NULL);    //设置线程的信号屏蔽码,语义与sigprocmask()相同,但对不允许屏蔽的Cancel信号和不允许响应的Restart信号进行了保护。被屏蔽的信号保存在信号队列中,可由sigpending()函数取出。 
  11.     if ((cpt = cfgopt(conn->copt, "ReadTimeout")))
  12.     {
  13.         timeout = cpt->numarg;
  14.     }
  15.     else
  16.     {
  17.         timeout = CL_DEFAULT_SCANTIMEOUT;
  18.     }
  19.     if (!timeout)
  20.         timeout = -1;
  21.     do
  22.     {
  23.         ret = command(conn->sd, conn->root, conn->limits, conn->options, conn->copt, timeout);  //这才是真正干事儿
  24.         if (ret == -1)
  25.         {
  26.             break;
  27.         }
  28.         switch (ret)
  29.         {
  30.         case COMMAND_SHUTDOWN:
  31.             pthread_mutex_lock(&exit_mutex);
  32.             progexit = 1;
  33.             kill(conn->mainpid, SIGTERM);           //这里给主线程,也就是服务端进程发送关闭信号
  34.             pthread_mutex_unlock(&exit_mutex);
  35.             break;
  36.         case COMMAND_RELOAD:
  37.             pthread_mutex_lock(&reload_mutex);
  38.             reload = 1;
  39.             pthread_mutex_unlock(&reload_mutex);
  40.             break;
  41.         
  42.         case COMMAND_SESSION:           //客户端传来命令session 我们仍在一个session当中 这里还要继续循环获取命令(但是这个是什么状态下要发送嗯这个命令的)  
  43.             session = TRUE;
  44.             timeout = 5;
  45.             break;
  46.         case COMMAND_END:
  47.             session = FALSE;
  48.             break;
  49.         }
  50.         if (session)
  51.         {
  52.             pthread_mutex_lock(&exit_mutex);
  53.             if (progexit)
  54.             {
  55.                 session = FALSE;
  56.             }
  57.             pthread_mutex_unlock(&exit_mutex);
  58.             pthread_mutex_lock(&reload_mutex);
  59.             if (conn->root_timestamp != reloaded_time)
  60.             {
  61.                 session = FALSE;
  62.             }
  63.             pthread_mutex_unlock(&reload_mutex);
  64.         }
  65.     }
  66.     while (session);
  67.     close(conn->sd);
  68.     cl_free(conn->root);
  69.     free(conn);
  70.     return;
  71. }

就这样,通过command,我们把任务又推卸给其它函数来做了. command是最终办事的函数,不过这要等下次再说了,因为实验室要关门了.











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值