关于ngx_trylock_accept_mutex的一些解释
關(guān)于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);
/* 有人說應(yīng)該加上ngx_accept_mutex_held = 0; */
}
這里我們好好分析一下ngx_trylock_accept_mutex函數(shù),它就能給我們答案:
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;
}
對照這個函數(shù),我們假想一個情景,若此時nginx有兩個worker,我們稱為A和B。當(dāng)A執(zhí)行這個函數(shù),并在調(diào)用ngx_shmtx_trylock時成功,這時它將listen fd注冊到自己的epoll中(即ngx_enable_accept_events),然后ngx_accept_mutex_held被置1。注意哦,這里ngx_enable_accept_events處理之后就將其置1是為了表達(dá)listen fd此時被A進(jìn)程注冊到epoll中了。很顯然這個時候B進(jìn)程由于獲取accept鎖失敗,自然就沒有權(quán)利accept了。當(dāng)進(jìn)程A在處理完accept之后,就會釋放accept鎖,讓B在下一輪競爭中能有機會獲取鎖來做accept。
if (ngx_accept_mutex_held) {
ngx_shmtx_unlock(&ngx_accept_mutex);
}
接下來B很爭氣,獲得了accept鎖,跟當(dāng)年進(jìn)程A一樣將listen fd加到epoll中,處理過程如出一轍。這個時候我們來看A進(jìn)程,由于這次在跟B的較量中敗北,但是ngx_accept_mutex_held為true,表明之前曾經(jīng)注冊過listen fd。別忘了失敗的代價就是要交出listen fd,皇帝的位置現(xiàn)在由B來做,王冠現(xiàn)在不屬于你了。由于此時只有B有權(quán)將listen fd注冊到自己的epoll中,其他的進(jìn)程(ngx_accept_mutex_held為true的進(jìn)程)就要將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是每個進(jìn)程私有了,可能在有些系統(tǒng)的設(shè)計里,epoll是線程(或者進(jìn)程)共享的。
--------------------- 本文來自 aweth0me 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/brainkick/article/details/9081017?utm_source=copy
總結(jié)
以上是生活随笔為你收集整理的关于ngx_trylock_accept_mutex的一些解释的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nginx源码初读(8)--让烦恼从数据
- 下一篇: HttpDNS功能说明及实现