关于ngx_trylock_accept_mutex的一些解释
關于nginx里面accept互斥鎖的處理,群里討論了很多次,很多人都提出了各種問題,比如問到:在ngx_process_events_and_timers中,為什么在釋放ngx_accept_mutex之后,不把ngx_accept_mutex_held清零?
if (ngx_accept_mutex_held) {
ngx_shmtx_unlock(&ngx_accept_mutex);
/* 有人說應該加上ngx_accept_mutex_held = 0; */
}
這里我們好好分析一下ngx_trylock_accept_mutex函數,它就能給我們答案:
ngx_int_t
ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
{
if (ngx_shmtx_trylock(&ngx_accept_mutex)) {
if (ngx_enable_accept_events(cycle) == NGX_ERROR) {
ngx_shmtx_unlock(&ngx_accept_mutex);
return NGX_ERROR;
}
ngx_accept_mutex_held = 1;
return NGX_OK;
}
if (ngx_accept_mutex_held) {
if (ngx_disable_accept_events(cycle) == NGX_ERROR) {
return NGX_ERROR;
}
ngx_accept_mutex_held = 0;
}
return NGX_OK;
}
對照這個函數,我們假想一個情景,若此時nginx有兩個worker,我們稱為A和B。當A執行這個函數,并在調用ngx_shmtx_trylock時成功,這時它將listen fd注冊到自己的epoll中(即ngx_enable_accept_events),然后ngx_accept_mutex_held被置1。注意哦,這里ngx_enable_accept_events處理之后就將其置1是為了表達listen fd此時被A進程注冊到epoll中了。很顯然這個時候B進程由于獲取accept鎖失敗,自然就沒有權利accept了。當進程A在處理完accept之后,就會釋放accept鎖,讓B在下一輪競爭中能有機會獲取鎖來做accept。
if (ngx_accept_mutex_held) {
ngx_shmtx_unlock(&ngx_accept_mutex);
}
接下來B很爭氣,獲得了accept鎖,跟當年進程A一樣將listen fd加到epoll中,處理過程如出一轍。這個時候我們來看A進程,由于這次在跟B的較量中敗北,但是ngx_accept_mutex_held為true,表明之前曾經注冊過listen fd。別忘了失敗的代價就是要交出listen fd,皇帝的位置現在由B來做,王冠現在不屬于你了。由于此時只有B有權將listen fd注冊到自己的epoll中,其他的進程(ngx_accept_mutex_held為true的進程)就要將listen fd從自己的epoll中移除(即ngx_disable_accept_events)。
if (ngx_accept_mutex_held) {
if (ngx_disable_accept_events(cycle) == NGX_ERROR) {
return NGX_ERROR;
}
ngx_accept_mutex_held = 0;
}
說到這里大家別混淆了,nginx的epoll是每個進程私有了,可能在有些系統的設計里,epoll是線程(或者進程)共享的。
--------------------- 本文來自 aweth0me 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/brainkick/article/details/9081017?utm_source=copy
總結
以上是生活随笔為你收集整理的关于ngx_trylock_accept_mutex的一些解释的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nginx源码初读(8)--让烦恼从数据
- 下一篇: Nginx配置中的log_format用