我讀Mongoose源碼----程序框架

Mongoose是一種WEB服務器,因爲最近在學習網絡編程,所以打算研究研究它的源碼,認真看了大部分,覺得學到的東西的確不少,拿出來分享一下,也和大家交流交流

至於什麼是WEB服務器,以及Mongoose作爲一種輕量級的WEB服務器,它有哪些優點,這裏給個鏈接:http://www.cnblogs.com/skynet/archive/2010/07/24/1784322.html

剛開始,也是看作者的文章才產生興趣讀源碼,所以分享很重要(^o^)

如果想快速的閱讀源碼,可以先預覽一下UserManual.md這個文件,用戶手冊告訴我們怎麼去使用這個服務器,以及如何使用它提供的功能。

好的,編譯運行請看那位吳哥的文章,這裏,我直接把我讀源碼的筆記整理出來:首先我們看程序的主體框架,細節決定成敗,但是從整理上入手,我們能走的更遠。

程序的框架:

Mongoose採用的是線程池模型,有兩個關鍵的數據結構,mg_callbacks和mg_context,前者是一系列函數指針集合,在程序的執行過程中我們會調用這些函數,後者則是Mongoose的核心,數據結構後面單獨分析,回到程序框架上來

main(){
//處理用戶的輸入
process_command_line_arguments();
//設置中斷信號
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
//開始
mg_start();
while(exit_flag == 0)
    sleep(1);
//結束
mg_stop();
}

程序的開始:

程序開始於mg_start,結束於mg_stop,在mg_start()中,分別生成主線程和工作線程,工作線程我們可以自己配置,默認是50個

mg_start_thread(master_thread,ctx)

mg_start_thread(worker_thread,ctx)

然後分爲兩條線路:

1.     Master_thread()中採用poll來處理監聽套接字,對於每一個監聽套接字,當有新的連接請求時,調用accept_new_connection()處理新的連接。accept_new_connection()中調用produce_socket()產生新的連接套接字,產生的連接套接字放入線程池隊列中,因爲是多線程,所以要考慮線程同步問題,這裏採用了“生產者---消費者”模型,很好的處理了同步問題

2.     worker_thread()中作爲消費者,我們調用consume_socket(),然後調用process_new_connection()來處理新的連接,實質是調用handle_request()函數,至此整個程序的框架一目瞭然

 

程序的結束:

我們在main函數中sleep了,當我們收到了信號例如鍵盤上的ctrl+c,

static voidWINCDECL signal_handler(int sig_num) {

  exit_flag = sig_num;

}

中修改了exit_flag,然後程序進入mg_stop(),

void mg_stop(struct mg_context *ctx) {
  ctx->stop_flag = 1;
  while (ctx->stop_flag != 2) {
    (void) mg_sleep(10);
  }
}

修改了mg->stop_flag = 1,然後等待其變爲2, 其實就是去清理線程數據,我們在master_thread()中看到最後一句ctx->stop_flag = 2,至此,程序就退出了,以上就是程序的結束流程。

程序的框架圖大體是這樣的:



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