Clamav殺毒軟體源碼分析筆記[七]

來源:互聯網
上載者:User
  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是最終辦事的函數,不過這要等下次再說了,因為實驗室要關門了.





相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.