動態建立程序(或執行緒)是比較耗費時間的,這樣導致較慢的客戶響應。動態建立的子程序(子執行緒)通常只用來為乙個客戶服務,這將導致系統上產生大量的細微程序(或執行緒)。程序間的切換將消耗大量的cpu時間。動態建立的子程序是當前程序的完整映像,當前程序必須謹慎地管理其分配的檔案描述符和堆記憶體等系統資源,否則子程序可能複製這些資源,從而使系統的可用資源急劇下降,進而影響伺服器的效能。
為了解決這些問題,我們使用了程序池和執行緒池這兩種技術。
httpd的程序池:
我們可以清楚地看到,當我們開啟httpd服務後,檢視程序時,有8個父程序都是9863的子程序,這就是httpd建立的程序池。
程序池中的所有子程序都執行著相同的**,並具有相同的屬性,比如優先順序,pgid等。因為程序池在伺服器啟動之初就建立好了,所以每個子程序都相對乾淨,即他們沒有開啟不必要的檔案描述符(從父程序繼承而來),也不會錯誤地使用大塊的堆記憶體。當有新的任務到來時,主程序通過某種程序間通訊的方式選擇程序池中的某個子程序來為之服務。相比於動態建立,選擇乙個已有的子程序(函式執行緒)的代價顯然要小得多。主線程需要將檔案描述符,傳遞給函式執行緒函式執行緒啟動後必須阻塞在獲取檔案描述符之前訊號量來控制主線程向函式執行緒通知獲取檔案描述符事件主線程在陣列中插入資料,以及函式執行緒獲取陣列中的資料必須是乙個互斥的過程父程序需要將檔案描述符傳遞給子程序由於檔案描述符是在fork之後建立,因此父子程序無法共享程序池中的程序必須阻塞在獲取到客戶端的檔案描述符之前傳遞檔案描述符時,不能僅僅傳遞乙個整型值,而是檔案描述符
#include#include#include#include#include#include#include#include#include#includestatic const int control_len = cmsg_len(sizeof(int));
/*檔案描述符傳送函式*/
void send_fd(int fd, int fd_to_send)
/*檔案描述符接收函式*/
int recv_fd(int fd)
int main() }
if(ret != 0)
send_fd(pipefd[1], c);//將接收到的檔案描述符寫入管道,供子程序讀取
close(c);
} }if(ret == 0)
; res = recv(c, recvbuff, 127, 0);
if(res <= 0)
printf("%d: %s\n", c, recvbuff);
send(c, "ok", 2, 0);
}} }
}
#include#include#include#include#include#include#include#include#include#include#includepthread_mutex_t mutex;
int clilink[8];//已經被接收但還未被處理的連線請求
sem_t sem;
/*初始化連線陣列*/
void initclilink()
}/*插入新接收的連線,等待處理*/
int insert(int c)
} pthread_mutex_unlock(&mutex);
if(i >= 8)
return -1;
return 0;
}/*獲取連線,進行處理*/
int getcli()
pthread_mutex_unlock(&mutex);
return c;
}void *pthread_fun(void *arg);
int main()
initclilink();
sem_init(&sem, 0, 0);//初始化訊號量值為0,使得函式執行緒阻塞
while(1)
if(insert(c) == -1)
sem_post(&sem);//訊號量+1,函式執行緒可以開始獲取陣列中等待的連線進行處理 }}
/*執行緒函式*/
void *pthread_fun(void *arg)
; int n = recv(c, buff, 127, 0);
if(n <= 0)
printf("%d: %s\n",c, buff);
send(c, "ok", 2, 0);}}}
執行緒池和程序池
案例 模擬多個客戶端一同去訪問服務端,讓服務端支援多個客戶端訪問,從而實現併發效果 不考慮粘包問題 import socket from threading import thread server socket.socket def communicate conn 開始通訊 while true...
程序池和執行緒池
系統啟動乙個新執行緒的成本是比較高的,因為它涉及與作業系統的互動。在這種情形下,使用執行緒池可以很好地提公升效能,尤其是當程式中需要建立大量生存期很短暫的執行緒時,更應該考慮使用執行緒池。執行緒池在系統啟動時即建立大量空閒的執行緒,程式只要將乙個函式提交給執行緒池,執行緒池就會啟動乙個空閒的執行緒來...
程序池和執行緒池
from concurrent.futures import threadpoolexecutor,processpoolexecutor import time,random,os def task name,n print s s is running name,os.getpid time.s...