原文:http://tengine.taobao.org/book/chapter_02.html
對於一個基本的web伺服器來說,事件通常有三種類型,網路事件、訊號、定時器。在之前的文章中,網路事件通過非同步非阻塞可以很好的解決掉。而如何處理訊號與定時器?
首先,訊號的處理。對nginx來說,有一些特定的訊號,代表著特定的意義。訊號會中斷掉程式當前的運行,在改變狀態後,繼續執行。如果是系統調用,則可能會導致系統調用的失敗,需要重入。對於nginx來說,如果nginx正在等待事件(epoll_wait時),如果程式收到訊號,在訊號處理函數處理完後,epoll_wait會返回錯誤,然後程式可再次進入epoll_wait調用。
另外,再來看看定時器。由於epoll_wait等函數在調用的時候是可以設定一個逾時時間的,所以nginx藉助這個逾時時間來實現定時器。nginx裡面的定時器事件是放在一顆維護定時器的紅/黑樹狀結構裡面,每次在進入epoll_wait前,先從該紅/黑樹狀結構裡面拿到所有定時器事件的最小時間,在計算出epoll_wait的逾時時間後進入epoll_wait。所以,當沒有事件產生,也沒有中斷訊號時,epoll_wait會逾時,也就是說,定時器事件到了。這時,nginx會檢查所有的逾時事件,將他們的狀態設定為逾時,然後再去處理網路事件。由此可以看出,當我們寫nginx代碼時,在處理網路事件的回呼函數時,通常做的第一個事情就是判斷逾時,然後再去處理網路事件。
我們可以用一段虛擬碼來總結一下nginx的事件處理模型:
while (true) { for t in run_tasks: t.handler(); update_time(&now); timeout = ETERNITY; for t in wait_tasks: /* sorted already */ if (t.time <= now) { t.timeout_handler(); } else { timeout = t.time - now; break; } nevents = poll_function(events, timeout); for i in nevents: task t; if (events[i].type == READ) { t.handler = read_handler; } else { /* events[i].type == WRITE */ t.handler = write_handler; } run_tasks_add(t);}
').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('
').text(i)); }; $numbering.fadeIn(1700); }); });
以上就介紹了[讀書筆記]1_初探nginx架構_3_處理訊號與定時器,包括了方面的內容,希望對PHP教程有興趣的朋友有所協助。