程序池模型

2021-09-20 20:33:34 字數 3961 閱讀 9298

程序池模型需要通過system v ipc機制或管道、訊號、檔案鎖等進行同步。以下是程序池的一般模型。

linux驚群現象:

驚群:驚群是指多個程序/執行緒在等待同一資源時,每當資源可用,所有的程序/執行緒都來競爭資源的現象。

accept、select、epoll實現程序池模型時的驚群現象:

1).linux多程序accept系統呼叫的驚群問題(注意,這裡沒有使用select、epoll等事件機制),在linux 2.6版本之前的版本存在,在之後的版本中解決掉了。

2).使用select epoll等事件機制,在linux早期的版本中,驚群問題依然存在(epoll_create在fork之前)。 原因與之前單純使用accept導致驚群,原因類似。epoll的驚群問題,同樣在之後的某個版本部分解決了。

3).epoll_create在fork之後呼叫,不能避免驚群問題,nginx使用互斥鎖,解決epoll驚群問題。

程序池中的程序呼叫accept如果阻塞在同乙個listen佇列中,有可能產生驚群現象(取決於linux版本):當一connect到達時,所有accept都會喚醒,但只有乙個accept會返回正確結果,其他的都會返回錯誤碼。

accept多程序實現:讓乙個程序bind乙個網路位址(可能是af_inet,af_unix或者其他任何你想要的),然後fork這個程序自己:

int s = socket(...)  

bind(s, ...)  

listen(s, ...)   

fork()  

fork自己幾次之後,每個程序阻塞在accept()函式這裡

在較老的unix系統中,當有連線到來時,accept()在每個阻塞在這的程序裡被喚醒。但是,只有這些程序中的乙個能夠真正的accept這個連線,其他的程序accept將返回eagain驚群造成結果是系統對使用者程序/執行緒頻繁的做無效的排程、上下文切換,系統系能大打折扣。

實現**:

伺服器端**:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define buflen 1024

#define pidnum 3

/*******************併發伺服器模型之一:預先分配好了程序的個數**********************/

static void handle_fork(int sockfd)else

printf("\n*****************通訊開始***************\n");

printf("正在與您通訊的客戶端是:%s: %d\n",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));

/******處理客戶端請求*******/

bzero(buf,buflen);

len = recv(newfd,buf,buflen,0);

if(len >0 && !strncmp(buf,"time",4))

/*關閉通訊的套接字*/

close(newfd);}}

int main(int argc, char **ar**)

else

printf("socket create success!\n");

/*設定伺服器端口*/    

if(ar**[2])

port = atoi(ar**[2]);

else

port = 4567;

/*設定偵聽佇列長度*/

if(ar**[3])

listnum = atoi(ar**[3]);

else

listnum = 3;

/*設定伺服器ip*/

bzero(&s_addr, sizeof(s_addr));

s_addr.sin_family = af_inet;

s_addr.sin_port = htons(port);

if(ar**[1])

s_addr.sin_addr.s_addr = inet_addr(ar**[1]);

else

s_addr.sin_addr.s_addr = inaddr_any;

/*把位址和埠幫定到套接字上*/

if((bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr))) == -1)else

printf("bind success!\n");

/*偵聽本地埠*/

if(listen(sockfd,listnum) == -1)else

printf("the server is listening!\n");

/*處理客戶端的連線*/

int i = 0;

for(i = 0; i < pidnum; i++)

/*關閉伺服器的套接字*/

close(sockfd);

return 0;

}客戶端**:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define buflen 1024

int main(int argc, char **ar**)

else

printf("socket create success!\n");

/*設定伺服器端口*/    

if(ar**[2])

port = atoi(ar**[2]);

else

port = 4567;

/*設定伺服器ip*/

bzero(&s_addr, sizeof(s_addr));

s_addr.sin_family = af_inet;

s_addr.sin_port = htons(port);

if (inet_aton(ar**[1], (struct in_addr *)&s_addr.sin_addr.s_addr) == 0)

/*開始連線伺服器*/    

if(connect(sockfd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr)) == -1)else

printf("conncet success!\n"); 

/******緩衝區清零*******/    

bzero(buf,buflen);

strcpy(buf,"time");

/******傳送訊息*******/

send(sockfd,buf,strlen(buf),0);

/******緩衝區清零*******/

bzero(buf,buflen);

/******接收訊息*******/

len = recv(sockfd,buf,buflen,0);

if(len > 0)

printf("伺服器的系統時間是:%s\n",buf);

close(sockfd); /*關閉連線*/

return 0;

}

程序池 執行緒池

程序池和執行緒池相似,所以這裡我們以程序池為例介紹,下面對程序池的討論完全適用於執行緒池 如果沒有特殊宣告 程序池是由伺服器預先建立的一組子程序,這些子程序的數目在3 10個之間 典型情況 執行緒池的數量應該和cpu數量差不多。程序池中的所有子程序都執行者相同的 並具有相同的屬性。因為程序池在伺服器...

執行緒池 程序池

執行緒池 程序池 池子解決什麼問題?1.建立 銷毀執行緒伴隨著系統開銷,如果過於頻繁會影響系統執行效率 2.執行緒併發數量過多,搶占系統資源,從而導致系統阻塞甚至宕機 3.能夠剛好的控制和管理池子裡面的執行緒和程序 concurrent.futures模組提供了高度封裝的非同步呼叫介面 thread...

程序池, 執行緒池

知識儲備 池 裝載固定數量介質,該介質值得是程序或者執行緒 為什麼要用?讓機器在自己可承受的範圍內去保證乙個高效的工作 from concurrent.futures import processpoolexecutor,threadpoolexecutor pool processpoolexec...