简体   繁体   中英

Architecture for multi-processing application in C: fork or fork + exec

My question is about more philosophical than technical issues.

Objective is to write a multiprocess (not multithread) program with one "master" process and N "worker" processes. Program is linux-only, async, event-based web-server, like nginx. So, the main problem is how to spawn "worker" processes.

In linux world there are two ways:

1). fork()

2). fork() + exec*() family

A short description for each way and what confused me in each of them.

First way with fork() is dirty, because forked process has copy (...on-write, i know) of parent memory: signal handlers, variables, file\\socket descriptors, environ and other, eg stack and heap. In conclusion, after fork i need to...hmm..."clear memory", for example, disable signal handlers, socket connections and other horrible things, inherited from parent, because child has a lot of data that he was not intended - breaks encapsulation, and many side-effects is possible.

The general way for this case is run infinite loop in forked process to handle some data and do some magic with socket pair, pipes or shared memory for creating communication channel between parent and child before and after fork() , because socket descriptors reopen in child and used same socket as parent.

Also, this is nginx-way: it has one executable binary, that use fork() for spawn child process.

The second way is similar to first, but have a difference with usage one of exec*() function in child process after fork() for run external binary. One important thing is that exec*() loads binary in current (forked) process memory, automatic clear stack, heap and do all other nasty job, so fork will look like a clearly new instance of program without copy of parent memory or something other trash.

There has another problem with communication establishing between parent and child: because forked process after exec*() remove all data inherited from parent, that i need somehow create a socket pair between parent and child. For example, create additional listen socket (domain or in another port) in parent and wait child connections and child should connect to parent after initialization.

The first way is simple, but confuse me, that is not a clear process, just a copy of parent memory, with many possible side-effects and trash, and need to keep in mind that forked process has many dependencies to parent code. Second way needs more time to support two binary, and not so elegant like single-file solution. Maybe, the best way is use fork() for process create and something to clear it memory without exec*() call, but I cant find any solution for second step.

In conclusion, I need help to decide which way to use: create one-file executable file like nginx, and use fork() , or create two separate files, one with "server" and one with "worker", and use fork() + exec*(worker) N times from "server", and want know for pros and cons for each way, maybe I missed something.

As a Linux Programmer, you have a rich library of multithreading process capabilities. Look at pthread and friends.

If you need a process per request, then fork and friends have been the most widely used since time immemorial.

For a multiprocess solution both options, fork and fork+exec, are almost equivalent and depends on the child and parent process context. If the child process executes the parents' text (binary) and needs all or a part of parents' staff (descriptors, signals etc) - it is a sign to use fork. If the child should execute a new binary and needs nothing from the parents' staff - it seems fork+exec much more suitable.

There is also a good function in the pthread library - pthread_atfork() . It allows to register handlers that will be called before and after fork. These handlers may perform all the necessary work (closing file descriptors, for example).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM