本文是基於半同步/半非同步程序池的實現,半同步/半非同步模型主要是主程序監視listen套接字,然後發訊號給子程序,子程序完成鏈結和讀寫資料。
1.使用epoll實現i/0復用;
2.實現訊號和i/o事件的統一事件源。
3.使用管道進行子程序和父程序的通訊。
**如下:
#ifndef processpool_h
#define processpool_h
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*描述乙個子程序的類,m_pid是目標子程序的pid,m_pipefd是父程序和子程序通訊用的管道*/
class process
public:
pid_t m_pid;
int m_pipefd[2];
};/*程序池類,將它定義為模板類是為了**復用。其模板引數是處理邏輯任務的類*/
template< typename t >
class processpool
return m_instance;
}~processpool()
/*啟動程序池*/
void run();
private:
void setup_sig_pipe();
void run_parent();
void run_child();
private:
/*程序池允許的最大子程序數量*/
static const int max_process_number = 16;
/*每個子程序最多能處理的客戶數量*/
static const int user_per_process = 65536;
/*epoll最多能處理的事件數*/
static const int max_event_number = 10000;
/*程序池中的程序總數*/
int m_process_number;
/*子程序在池中的序號,從0開始*/
int m_idx;
/*每個程序都有乙個epoll核心時間,用m_epollfd標識*/
int m_epollfd;
/*監聽socket*/
int m_listenfd;
/*子程序通過m_stop來決定是否停止執行*/
int m_stop;
/*儲存所有子程序的描述資訊*/
process* m_sub_process;
/*程序池靜態例項*/
static processpool< t >* m_instance;
};template< typename t >
processpool< t >* processpool< t >::m_instance = null;
/*用於處理訊號的管道,以實現同意事件源。後面稱之為訊號管道*/
static int sig_pipefd[2];
static int setnonblocking( int fd )
static void addfd( int epollfd, int fd )
/*從epollfd標識的epoll核心時間表中刪除fd上的所有註冊事件*/
static void removefd( int epollfd, int fd )
/*訊號處理函式*/
static void sig_handler( int sig )
/*設定訊號處理函式*/
static void addsig( int sig, void( handler )(int), bool restart = true )
sigfillset( &sa.sa_mask );
assert( sigaction( sig, &sa, null ) != -1 );
}/*程序池建構函式。引數listenfd是監聽socket,它必須在建立程序池之前被建立,否則子程序無法直接引用它。
引數process_number指定程序池中子程序的數量*/
template< typename t >
processpool< t >::processpool( int listenfd, int process_number )
: m_listenfd( listenfd ), m_process_number( process_number ), m_idx( -1 ), m_stop( false )
else
}}/*統一事件源*/
template< typename t >
void processpool< t >::setup_sig_pipe()
/*父程序中m_idx值為-1,子程序m_idx值大於等於0,我們據此判斷接下來要執行的是父程序**還是子程序***/
template< typename t >
void processpool< t >::run()
run_parent();
}template< typename t >
void processpool< t >::run_child()
for ( int i = 0; i < number; i++ )
else
addfd( m_epollfd, connfd );
/*模板類t必須實現init方法,以初始化乙個客戶連線。我們直接使用connfd來索引邏輯處理物件(t型別的物件),
以提高程式效率*/
users[connfd].init( m_epollfd, connfd, client_address );}}
/*下面處理子程序接收到的訊號*/
else if( ( sockfd == sig_pipefd[0] ) && ( events[i].events & epollin ) )
else
break;
}case sigterm:
case sigint:
default:}}
}}
else if( events[i].events & epollin )
else}}
delete users;
users = null;
close( pipefd );
//close( m_listenfd );
及所謂的「物件由哪個函式建立,就應該由哪個函式銷毀」*/
close( m_epollfd );
}template< typename t >
void processpool< t >::run_parent()
for ( int i = 0; i < number; i++ )
i = (i+1)%m_process_number;
}while( i != sub_process_counter );
if( m_sub_process[i].m_pid == -1 )
sub_process_counter = (i+1)%m_process_number;
//send( m_sub_process[sub_process_counter++].m_pipefd[0], ( char* )&new_conn, sizeof( new_conn ), 0 );
send( m_sub_process[i].m_pipefd[0], ( char* )&new_conn, sizeof( new_conn ), 0 );
printf( "send request to child %d\n", i );
//sub_process_counter %= m_process_number;
}/*下面處理父程序接收到的訊號*/
else if( ( sockfd == sig_pipefd[0] ) && ( events[i].events & epollin ) )
else}}
m_stop = true;
for( int i = 0; i < m_process_number; ++i )
}break;
}case sigterm:
case sigint:
}break;
}default:}}
}}
else}}
//close( m_listenfd );
/*由建立者關閉上面這個檔案描述符*/
close( m_epollfd );
}#endif
如何實現程序池
有位站友問,如何在linux下實現程序池技術,原貼見 之前雖對程序池這個名詞早有耳聞,但一直沒有真正接觸過。乍一聽好像有點複雜,但稍微一想卻也簡單,下面我就按自己的想法來實現乙個簡單的模型。跟最簡單的資源管理一樣,程序池技術的應該致少由以下兩部分組成 資源程序 預先建立好的空閒程序,管理程序會把工作...
Linux 程序池實現
程序池在伺服器應用中有很多很多 下面是半同步半非同步程序池的實現 ifndef processpool h define processpool h include include include include include include include include include inc...
記憶體池 程序池 執行緒池介紹及執行緒池C 實現
平常我們使用new malloc在堆區申請一塊記憶體,但由於每次申請的記憶體大小不一樣就會產生很多記憶體碎片,造成不好管理與浪費的情況。記憶體池則是在真正使用記憶體之前,先申請分配一定數量的 大小相等 一般情況下 的記憶體塊留作備用。當有新的記憶體需求時,就從記憶體池中分出一部分記憶體塊,若記憶體塊...