簡體   English   中英

C中多處理應用程序的體系結構:fork或fork + exec

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM