[英]Architecture for multi-processing application in C: fork or fork + exec
我的問題是關於哲學而不是技術問題。
目的是編寫一個具有一個“主”進程和N個“工人”進程的多進程(不是多線程)程序。 程序是僅Linux,基於事件的異步Web服務器,例如nginx。 因此,主要問題是如何生成“工人”流程。
在linux world中,有兩種方法:
1)。 fork()
2)。 fork()
+ exec*()
系列
每種方式的簡短說明,以及每種方式的困惑之處。
用fork()
第一種方法很臟,因為分叉的進程具有父內存的副本(...寫時寫,我知道):信號處理程序,變量,文件\\套接字描述符,環境和其他(例如堆棧和堆)。 總之,在派生之后,我需要...嗯...“清除內存”,例如,禁用信號處理程序,套接字連接和其他從父級繼承的可怕內容,因為子級擁有大量他不想要的數據-破壞封裝,可能會產生許多副作用。
這種情況的一般方法是在派生進程中運行無限循環,以處理一些數據並使用套接字對,管道或共享內存做一些魔術,以在fork()
之前和之后創建父子之間的通信通道,因為套接字描述符在子對象中重新打開並使用與父代相同的套接字。
同樣,這是nginx方式:它具有一個可執行二進制文件,該文件使用fork()
生成子進程。
第二種方法與第一種類似,但是在運行外部二進制文件的fork()
之后,子進程中的exec*()
函數的用法有所不同。 一件重要的事情是exec*()
在當前(分支)的進程內存中加載二進制文件,自動清除堆棧,堆並完成所有其他令人討厭的工作,因此fork看起來像是一個清晰的程序新實例,而沒有父內存或其他副本垃圾。
父與子之間的通信建立還有另一個問題:因為exec*()
之后的派生進程刪除了從父繼承的所有數據,所以我需要以某種方式在父與子之間創建一個套接字對。 例如,在父級中創建其他偵聽套接字(域或其他端口),然后等待子級連接,並且子級應在初始化后連接到父級。
第一種方法很簡單,但是使我感到困惑,這不是一個清晰的過程,僅僅是父內存的副本,具有許多可能的副作用和垃圾,並且需要記住,分叉的過程與父代碼有很多依賴關系。 第二種方式需要更多時間來支持兩個二進制文件,而不是像單文件解決方案那樣優雅。 也許,最好的方法是使用fork()
進行進程創建,並通過某種方式清除內存,而無需exec*()
調用,但是我找不到第二步的任何解決方案。
總之,我需要幫助來決定使用哪種方式:創建一個像nginx這樣的文件可執行文件,並使用fork()
,或者創建兩個單獨的文件,一個文件帶有“服務器”,另一個文件帶有“ worker”,然后使用fork()
+ exec*(worker)
N次來自“服務器”,並且想知道每種方法的優缺點,也許我錯過了一些東西。
作為Linux程序員,您擁有豐富的多線程處理功能庫。 看看pthread和朋友。
如果您需要每個請求一個流程,那么自遠古以來,fork和朋友一直是使用最廣泛的。
對於多進程解決方案,fork和fork + exec這兩個選項幾乎相等,並且取決於子進程和父進程的上下文。 如果子進程執行父母的文本(二進制)並且需要父母的全部或部分職員(描述符,信號等),則這是使用fork的標志。 如果孩子應該執行一個新的二進制文件並且不需要父母的任何幫助,那么fork + exec似乎更合適。
pthread庫中還有一個很好的功能-pthread_atfork() 。 它允許注冊將在fork之前和之后調用的處理程序。 這些處理程序可以執行所有必要的工作(例如,關閉文件描述符)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.