進程池線程池

池的概念

由於服務器的硬件資源“充裕”,那麼提高服務器性能的一個很直接的方法就是以空間換時間,即“浪費”服務器的硬件資源,以換取其運行效率。這就是池的概念。池是一組資源的集合,這組資源在服務器啓動之初就完全被創建並初始化,這稱爲靜態資源分配。當服務器進入正式運行階段,即開始處理客戶請求的時候,如果它需要相關的資源,就可以直接從池中獲取,無需動態分配。很顯然,直接從池中取得所需資源比動態分配資源的速度要快得多,因爲分配系統資源的系統調用都是很耗時的。當服務器處理完一個客戶連接後,可以把相關的資源放回池中,無需執行系統調用來釋放資源。從最終效果來看,池相當於服務器管理系統資源的應用設施,它避免了服務器對內核的頻繁訪問。

池可以分爲多種,常見的有內存池、進程池、線程池和連接池。


內存池

內存池是一種內存分配方式。通常我們習慣直接使用new、malloc等系統調用申請分配內存,這樣做的缺點在於:由於所申請內存塊的大小不定,當頻繁使用時會造成大量的內存碎片並進而降低性能。

內存池則是在真正使用內存之前,先申請分配一定數量的、大小相等(一般情況下)的內存塊留作備用。當有新的內存需求時,就從內存池中分出一部分內存塊,若內存塊不夠再繼續申請新的內存。這樣做的一個顯著優點是,使得內存分配效率得到提升。


進程池和線程池

進程池和線程池相似,所以這裏我們以進程池爲例進行介紹。如沒有特殊聲明,下面對進程池的描述也適用於線程池。

進程池是由服務器預先創建的一組子進程,這些子進程的數目在 3~10 個之間(當然這只是典型情況)。線程池中的線程數量應該和 CPU 數量差不多。

進程池中的所有子進程都運行着相同的代碼,並具有相同的屬性,比如優先級、 PGID 等。

當有新的任務來到時,主進程將通過某種方式選擇進程池中的某一個子進程來爲之服務。相比於動態創建子進程,選擇一個已經存在的子進程的代價顯得小得多。至於主進程選擇哪個子進程來爲新任務服務,則有兩種方法:

1)主進程使用某種算法來主動選擇子進程。最簡單、最常用的算法是隨機算法和 Round Robin (輪流算法)。

2)主進程和所有子進程通過一個共享的工作隊列來同步,子進程都睡眠在該工作隊列上。當有新的任務到來時,主進程將任務添加到工作隊列中。這將喚醒正在等待任務的子進程,不過只有一個子進程將獲得新任務的“接管權”,它可以從工作隊列中取出任務並執行之,而其他子進程將繼續睡眠在工作隊列上。

當選擇好子進程後,主進程還需要使用某種通知機制來告訴目標子進程有新任務需要處理,並傳遞必要的數據。最簡單的方式是,在父進程和子進程之間預先建立好一條管道,然後通過管道來實現所有的進程間通信。在父線程和子線程之間傳遞數據就要簡單得多,因爲我們可以把這些數據定義爲全局,那麼它們本身就是被所有線程共享的。

線程池主要用於:

1)需要大量的線程來完成任務,且完成任務的時間比較短。 比如WEB服務器完成網頁請求這樣的任務,使用線程池技術是非常合適的。因爲單個任務小,而任務數量巨大。但對於長時間的任務,比如一個Telnet連接請求,線程池的優點就不明顯了。因爲Telnet會話時間比線程的創建時間大多了。

2)對性能要求苛刻的應用,比如要求服務器迅速響應客戶請求。

3)接受突發性的大量請求,但不至於使服務器因此產生大量線程的應用。

進程城實現源碼:

如何在Linux下實現進程池技術,原貼見:
http://topic.csdn.net/u/20090206/16/b424e1c1-90dc-4589-a63f-1d90ed6560ae.html

  1. //主接收網絡消息進程  
  2. int main()  
  3. {  
  4.     int iReLen;  
  5.     char szBuffer[64];  
  6.     ...  
  7.     //初始化進程池  
  8.     InitProcessPoll();  
  9.     ....  
  10.     while(1)  
  11.     {  
  12.         iRelen = recv(iSock, szBuffer, sizeof(szbuffer), 0);  
  13.         if (iRelen > 0)  
  14.         {  
  15.             SubmitWork(szBuffer, iRelen);   //提交工作到資源進程  
  16.         }     
  17.     }  
  18.     ...  
  19. }  
  20.   
  21. //  
  22. int SubmitWork(void *pBuffer, int iMsgLen)  
  23. {  
  24.     int iMsgQueID;  
  25.       
  26.     iMsgQueID = GetMsgQue(key, 0); //取得跟管理進程通信的消息隊更句柄;  
  27.       
  28.     msgsnd(iMsgQueID, pBuffer, iMsgLen, 0);  
  29. }  
  30.   
  31. int InitProcessPoll(const int iProcessNum)  
  32. {  
  33.     int iPid;  
  34.       
  35.     //創建管理進程  
  36.     iPid = fork();  
  37.     if (iPid == 0)  
  38.     {  
  39.         InitMngProcess(iProcessNum);  
  40.     }     
  41.     return 0;  
  42. }  
  43.   
  44. typedef struct  
  45. {  
  46.     int pid;  
  47.     int iFlag;  
  48. } T_ProcessStatus;  
  49.   
  50. //指向資源進程管理結構  
  51. T_ProcessStatus *pProcessMng = NULL;  
  52.   
  53. //記錄有總共有多少個資源進程  
  54. INT32 iMaxProcessNum = 0;  
  55.   
  56. //初始管理進程管理結構並創建資源子進程,最後接收外部工作請求並分發到資源進行進行處理  
  57. InitMngProcess(const int iProcessNum)  
  58. {  
  59.     int i;  
  60.     int iPid;  
  61.     int iRtn;  
  62.     int iMsgLen;  
  63.     int iMsgQue1, iMsgQue2;  
  64.     char szBuffer[64];  
  65.       
  66.     //創建管理進程結構  
  67.     pProcessMng = calloc(iProcessNum, sizeof(T_ProcessStatus))  
  68.   
  69.     for (i = 0; i < iProcessNum; i++)  
  70.     {  
  71.         iPid = fork();  
  72.         if (iPid == 0);  
  73.         {  
  74.             //資源進程;  
  75.             ResourceProcess();  
  76.         }  
  77.         pProcessMng[i].pid = iPid; //記錄資源進程的進程號  
  78.         pProcessMng[i].iFlag = 0;   //把資源進程置爲空閒  
  79.     }  
  80.       
  81.     iMaxProcessNum = iProcessNum;  
  82.   
  83.     //創建外部跟管理進程通信的消息隊列;  
  84.     iMsgQue1 = CreateMsgQue();  
  85.   
  86.     //創建管理進程跟資源進程通信的消息隊列;  
  87.     iMsgQue2 = CreateMsgQue();  
  88.   
  89.     //安裝資源進程回收信號處理函數  
  90.     signal(SIGUSR1, ReleaseAProcess);     
  91.   
  92.     //開始接收外部傳入的任務  
  93.     while(1)  
  94.     {  
  95.         //接收外部的工作請求  
  96.         iMsgLen = msgrcv(iMsgQue1, szBuffer, sizeof(szBuffer), 0);  
  97.           
  98.         //轉發工作請求到資源進程處理消息隊列  
  99.         iRtn = msgsnd(iMsgQue2, szBuffer, iMsgLen, 0);  
  100.       
  101.         //通知其中的一個空閒資源進程進行處理  
  102.         NoticeAIdleProcess();  
  103.     }  
  104. }  
  105.   
  106. //通知一個空閒資源進程進行處理  
  107. int NoticeAIdleProcess()  
  108. {  
  109.     int i;  
  110.       
  111.     for (i = 0; i < iMaxProcessNum; i++)  
  112.     {  
  113.         if (pProcessMng[i].iFlag == 0)  
  114.         {  
  115.             pProessMng[i].Flag = 1;  
  116.             kill(processMng[i].pid, SIGUSR1);  
  117.             return 0;  
  118.         }  
  119.     }  
  120.       
  121.     return -1;    
  122. }  
  123.   
  124. //回收一個處理完成的資源進程  
  125. void ReleaseAProcess(int iPid)  
  126. {  
  127.     int i;  
  128.       
  129.     for (i = 0; i < iMaxProcessNum; i++)  
  130.     {  
  131.         if (pProessMng[i].pid == iPid)  
  132.         {  
  133.             pProcessMng[i].iFlag = 0;  
  134.             return;  
  135.         }  
  136.     }  
  137.   
  138.     return;  
  139. }  
  140.   
  141. //資源進程的處理  
  142. void ResourceProcess()  
  143. {  
  144.     //安裝有工作通知信號處理  
  145.     signal(SIGUSR1, SIG_IGN);  
  146.   
  147.     //設置只對SIGUSR1信號感興趣  
  148.     sigprocmask()  
  149.     while(1)  
  150.     {  
  151.         //沒有消息處理時掛起  
  152.         pause();  
  153.           
  154.         //處理工作  
  155.         void StartWork()  
  156.   
  157.         //通知管理進程工作處理完成  
  158.         NoticeMngProcessFinishedWork();   
  159.     }  
  160. }  
  161.   
  162. //處理消息  
  163. void StartWork()  
  164. {  
  165.     char szBuffer[64];  
  166.     int iMsgID;  
  167.     int iRtn;  
  168.       
  169.     iMsgID = msgget();  
  170.     iRtn = msgrcv(iMsgID, szBuffer, sizeof(szBuffer), 0);  
  171.       
  172.     //現在在子進程裏取得了需要處理的消息,可以開始處理該消息直到消息處理完成  
  173.   
  174.     return;   
  175. }  
  176.   
  177. //通知管理進程回收資源進程  
  178. void NoticeMngProcessFinishedWork();  
  179. {  
  180.     kill(MngProcessPid, SIGUSR1);  
  181.       
  182.     return;  
  183. }  

[cpp] view plain copy
  1. //主接收網絡消息進程  
  2. int main()  
  3. {  
  4.     int iReLen;  
  5.     char szBuffer[64];  
  6.     ...  
  7.     //初始化進程池  
  8.     InitProcessPoll();  
  9.     ....  
  10.     while(1)  
  11.     {  
  12.         iRelen = recv(iSock, szBuffer, sizeof(szbuffer), 0);  
  13.         if (iRelen > 0)  
  14.         {  
  15.             SubmitWork(szBuffer, iRelen);   //提交工作到資源進程  
  16.         }     
  17.     }  
  18.     ...  
  19. }  
  20.   
  21. //  
  22. int SubmitWork(void *pBuffer, int iMsgLen)  
  23. {  
  24.     int iMsgQueID;  
  25.       
  26.     iMsgQueID = GetMsgQue(key, 0); //取得跟管理進程通信的消息隊更句柄;  
  27.       
  28.     msgsnd(iMsgQueID, pBuffer, iMsgLen, 0);  
  29. }  
  30.   
  31. int InitProcessPoll(const int iProcessNum)  
  32. {  
  33.     int iPid;  
  34.       
  35.     //創建管理進程  
  36.     iPid = fork();  
  37.     if (iPid == 0)  
  38.     {  
  39.         InitMngProcess(iProcessNum);  
  40.     }     
  41.     return 0;  
  42. }  
  43.   
  44. typedef struct  
  45. {  
  46.     int pid;  
  47.     int iFlag;  
  48. } T_ProcessStatus;  
  49.   
  50. //指向資源進程管理結構  
  51. T_ProcessStatus *pProcessMng = NULL;  
  52.   
  53. //記錄有總共有多少個資源進程  
  54. INT32 iMaxProcessNum = 0;  
  55.   
  56. //初始管理進程管理結構並創建資源子進程,最後接收外部工作請求並分發到資源進行進行處理  
  57. InitMngProcess(const int iProcessNum)  
  58. {  
  59.     int i;  
  60.     int iPid;  
  61.     int iRtn;  
  62.     int iMsgLen;  
  63.     int iMsgQue1, iMsgQue2;  
  64.     char szBuffer[64];  
  65.       
  66.     //創建管理進程結構  
  67.     pProcessMng = calloc(iProcessNum, sizeof(T_ProcessStatus))  
  68.   
  69.     for (i = 0; i < iProcessNum; i++)  
  70.     {  
  71.         iPid = fork();  
  72.         if (iPid == 0);  
  73.         {  
  74.             //資源進程;  
  75.             ResourceProcess();  
  76.         }  
  77.         pProcessMng[i].pid = iPid; //記錄資源進程的進程號  
  78.         pProcessMng[i].iFlag = 0;   //把資源進程置爲空閒  
  79.     }  
  80.       
  81.     iMaxProcessNum = iProcessNum;  
  82.   
  83.     //創建外部跟管理進程通信的消息隊列;  
  84.     iMsgQue1 = CreateMsgQue();  
  85.   
  86.     //創建管理進程跟資源進程通信的消息隊列;  
  87.     iMsgQue2 = CreateMsgQue();  
  88.   
  89.     //安裝資源進程回收信號處理函數  
  90.     signal(SIGUSR1, ReleaseAProcess);     
  91.   
  92.     //開始接收外部傳入的任務  
  93.     while(1)  
  94.     {  
  95.         //接收外部的工作請求  
  96.         iMsgLen = msgrcv(iMsgQue1, szBuffer, sizeof(szBuffer), 0);  
  97.           
  98.         //轉發工作請求到資源進程處理消息隊列  
  99.         iRtn = msgsnd(iMsgQue2, szBuffer, iMsgLen, 0);  
  100.       
  101.         //通知其中的一個空閒資源進程進行處理  
  102.         NoticeAIdleProcess();  
  103.     }  
  104. }  
  105.   
  106. //通知一個空閒資源進程進行處理  
  107. int NoticeAIdleProcess()  
  108. {  
  109.     int i;  
  110.       
  111.     for (i = 0; i < iMaxProcessNum; i++)  
  112.     {  
  113.         if (pProcessMng[i].iFlag == 0)  
  114.         {  
  115.             pProessMng[i].Flag = 1;  
  116.             kill(processMng[i].pid, SIGUSR1);  
  117.             return 0;  
  118.         }  
  119.     }  
  120.       
  121.     return -1;    
  122. }  
  123.   
  124. //回收一個處理完成的資源進程  
  125. void ReleaseAProcess(int iPid)  
  126. {  
  127.     int i;  
  128.       
  129.     for (i = 0; i < iMaxProcessNum; i++)  
  130.     {  
  131.         if (pProessMng[i].pid == iPid)  
  132.         {  
  133.             pProcessMng[i].iFlag = 0;  
  134.             return;  
  135.         }  
  136.     }  
  137.   
  138.     return;  
  139. }  
  140.   
  141. //資源進程的處理  
  142. void ResourceProcess()  
  143. {  
  144.     //安裝有工作通知信號處理  
  145.     signal(SIGUSR1, SIG_IGN);  
  146.   
  147.     //設置只對SIGUSR1信號感興趣  
  148.     sigprocmask()  
  149.     while(1)  
  150.     {  
  151.         //沒有消息處理時掛起  
  152.         pause();  
  153.           
  154.         //處理工作  
  155.         void StartWork()  
  156.   
  157.         //通知管理進程工作處理完成  
  158.         NoticeMngProcessFinishedWork();   
  159.     }  
  160. }  
  161.   
  162. //處理消息  
  163. void StartWork()  
  164. {  
  165.     char szBuffer[64];  
  166.     int iMsgID;  
  167.     int iRtn;  
  168.       
  169.     iMsgID = msgget();  
  170.     iRtn = msgrcv(iMsgID, szBuffer, sizeof(szBuffer), 0);  
  171.       
  172.     //現在在子進程裏取得了需要處理的消息,可以開始處理該消息直到消息處理完成  
  173.   
  174.     return;   
  175. }  
  176.   
  177. //通知管理進程回收資源進程  
  178. void NoticeMngProcessFinishedWork();  
  179. {  
  180.     kill(MngProcessPid, SIGUSR1);  
  181.       
  182.     return;  
  183. }  



發佈了41 篇原創文章 · 獲贊 33 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章