在nginx中,master進程與worker進程之間使用了全雙工通訊方式--socketpair。 socketpair 函數成功執行後會建立一對已經建立連線的socket對,兩個相互通訊的進程分別使用其中一個socket進行讀寫操作,就能夠實現兩個進程間的通訊。
查看nginx原始碼,可以看到,下面的函數創建了socketpair
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn) { u_long on; ngx_pid_t pid; ngx_int_t s; /. ......省略...... ./ if (respawn != NGX_PROCESS_DETACHED) { /* Solaris 9 still has no AF_LOCAL */ //创建socketpair if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "socketpair() failed while spawning \"%s\"", name); return NGX_INVALID_PID; } //非阻塞 if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //非阻塞 if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //异步 on = 1; if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置将要在文件描述词fd上接收SIGIO 或 SIGURG事件信号的进程或进程组标识 。 if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置close_on_exec,当通过exec函数族创建了新进程后,原进程的该socket会被关闭 if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置close_on_exec,当通过exec函数族创建了新进程后,原进程的该socket会被关闭 if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } ngx_channel = ngx_processes[s].channel[1]; } else { ngx_processes[s].channel[0] = -1; ngx_processes[s].channel[1] = -1; } ngx_process_slot = s; pid = fork(); switch (pid) { case -1: ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; case 0: //fork成功,子进程创建,同时相关socket描述符也会被复制一份 ngx_pid = ngx_getpid(); proc(cycle, data); break; default: break; } /. ......省略...... ./ return pid; }
fork成功後,原始進程的descriptor也會被複製一份,如果在fork的進程中該描述符不再使用,需要我們及時關閉。
如果我們使用的是 fork->exec函數族 的形式創建新進程的話,我們可以採用更好的辦法來確保原有的descriptor被正常關閉,避免資源的洩漏。也就是上邊程式碼中對socket呼叫fcntl(FD_CLOEXEC)函數,設定該socket的屬性:當exec函數族被呼叫後,該socket會被自動關閉。使用這種在socket創建後立即設定FD_CLOEXEC屬性的辦法,避免了我們在exec創建進程前手動關閉相關socket的操作,尤其是當有大量的descriptor被創建、管理的時候非常實用。
很多時候我們是使用下邊的方法進行操作的:
#include <sys> #include <sys> #include <stdlib.h> #include <stdio.h> int main() { pid_t pid; int fds[2]; int valRead, valWrite; if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) { return 0; } pid = fork(); if (0 == pid) { pid = getpid(); printf("[%d]-child process start", pid); close(fds[0]); //read write on fds[1] write(fds[1], &valWrite, sizeof(valWrite)); read(fds[1], &valRead, sizeof(valRead)); } else if (0 <p> 可以看到,fork前,當前進程創建了一對socket,也就是socketpair。對於這對socket,可以看作一個是伺服器端fds[0],另一個是客戶端fds[1],透過fds[0]與fds[1]之間建立的鏈接,我們可以完成全雙工通信。 </p> <p> fork執行後,創建了子進程。在子進程中,先前父進程所建立的socketpair自然也會被複製一份為fds',存在於子進程中。父進程繼續執行。這時候,在父進程和子進程中會存在相同socketpair。 </p> <p> 試想,我們在主進程中向fds[0]寫入數據,在子進程中的fds'[1]上就會讀取到該數據,這樣就實現了父進程與子進程間的通信。當然,在主程序fds[1]上寫數據,在子程序fds'[0]上也會讀到寫入的數據。我們實際使用中,只需要保留一對socket用來通訊就可以了,另外兩個socket就可以分別在父進程和子進程中關閉不用了。 </p> <p> 當然了,如果我們能夠把fds中的一個socket透過某種方式傳遞給另一個進程,那麼也可以實現socketpair進程間通訊了。 </p> <br> <p> 以上就介紹了nginx 進程間通訊-socketpair,包含了方面的內容,希望對PHP教程有興趣的朋友有所幫助。 </p> <p> </p></stdio.h></stdlib.h></sys></sys>

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP不是在消亡,而是在不斷適應和進化。 1)PHP從1994年起經歷多次版本迭代,適應新技術趨勢。 2)目前廣泛應用於電子商務、內容管理系統等領域。 3)PHP8引入JIT編譯器等功能,提升性能和現代化。 4)使用OPcache和遵循PSR-12標準可優化性能和代碼質量。

PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。

在PHP中,trait適用於需要方法復用但不適合使用繼承的情況。 1)trait允許在類中復用方法,避免多重繼承複雜性。 2)使用trait時需注意方法衝突,可通過insteadof和as關鍵字解決。 3)應避免過度使用trait,保持其單一職責,以優化性能和提高代碼可維護性。

依賴注入容器(DIC)是一種管理和提供對象依賴關係的工具,用於PHP項目中。 DIC的主要好處包括:1.解耦,使組件獨立,代碼易維護和測試;2.靈活性,易替換或修改依賴關係;3.可測試性,方便注入mock對象進行單元測試。

SplFixedArray在PHP中是一種固定大小的數組,適用於需要高性能和低內存使用量的場景。 1)它在創建時需指定大小,避免動態調整帶來的開銷。 2)基於C語言數組,直接操作內存,訪問速度快。 3)適合大規模數據處理和內存敏感環境,但需謹慎使用,因其大小固定。

PHP通過$\_FILES變量處理文件上傳,確保安全性的方法包括:1.檢查上傳錯誤,2.驗證文件類型和大小,3.防止文件覆蓋,4.移動文件到永久存儲位置。

JavaScript中處理空值可以使用NullCoalescingOperator(??)和NullCoalescingAssignmentOperator(??=)。 1.??返回第一個非null或非undefined的操作數。 2.??=將變量賦值為右操作數的值,但前提是該變量為null或undefined。這些操作符簡化了代碼邏輯,提高了可讀性和性能。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

記事本++7.3.1
好用且免費的程式碼編輯器

Dreamweaver CS6
視覺化網頁開發工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具