Ни в чем. Это просто устаревшая концепция, сохраняющаяся ради совместимости.
Single Unix Specification говорит следующее:
There are two reasons why POSIX programmers call fork(). One reason is to create a new thread of control within the same program (which was originally only possible in POSIX by creating a new process); the other is to create a new process running a different program. In the latter case, the call to fork() is soon followed by a call to one of the exec functions.
То есть буквально, у fork-а есть два применения: создание нового процесса из нового бинарника и создание нового «потока» в рамках текущего процесса. В обоих случаях у него есть недостатки, происходящие из самого принципа fork-а:
1) При создании процесса сначала копируется адресное пространство (не память, а именно адресное пространство — у каждого процесса оно в любом случае свое), дескрипторы и прочие ресурсы, чтоб сразу же их освободить (эта проблема частично решается vfork-ом)
2) При создании потока опять же копируется адресное пространство вместо исполнения в том же.
Мне на ум приходит единственное применение, могущее быть полезным: создание песочниц a-la Chrome/IE7. Создание нового процесса копированием старого будет на пару миллионов (несколько миллисекунд на современных процессорах) тактов дешевле — для тех, кому важно создание песочниц в огромных количествах (и по какой либо причине «префорк» пула таких песочниц не подходит) это может оказаться существенным.
Есть еще одна проблема помимо сравнительно небольшого снижения производительности в двух наиболее часто используемых сценариях. Вот как описывает проблему все тот же SUS:
The general problem with making fork() work in a multi-threaded world is what to do with all of the threads. There are two alternatives. One is to copy all of the threads into the new process. This causes the programmer or implementation to deal with threads that are suspended on system calls or that might be about to execute system calls that should not be executed in the new process. The other alternative is to copy only the thread that calls fork(). This creates the difficulty that the state of process-local resources is usually held in process memory. If a thread that is not calling fork() holds a resource, that resource is never released in the child process because the thread whose job it is to release the resource does not exist in the child process.
В современном дизайне ПО существует такое довольно важное понятие, как
связность. Так вот, традиционный юникс-процесс имеет низкую связность. Он одновременно является контейнером ресурсов (упрощая, можно сказать, что это абстракция памяти) и единицей исполнения (абстракция процессора).
Posix thread-ы призваны решить данную проблему, но они несовместимы с fork. Так что лучше пользоваться подходом, описанным все в той же SUS:
When a programmer is writing a multi-threaded program, the first described use of fork(), creating new threads in the same program, is provided by the pthread_create() function. The fork() function is thus used only to run new programs, and the effects of calling functions that require certain resources between the call to fork() and the call to an exec function are undefined.
Пользоваться форком ТОЛЬКО для выполнения новой программы, для всего остального пользоваться pthread_create.