В чем разница между fork () и vfork ()?


13

Я хотел бы подробно понять разницу между fork () и vfork (). Я не смог полностью переварить справочную страницу.

Я также хотел бы пояснить комментарий одного из моих коллег: « В текущем Linux нет vfork (), даже если вы его вызываете, он будет внутренне вызывать fork () ».

Ответы:


24

Справочные страницы обычно являются краткими справочными документами. Википедия - лучшее место для концептуальных объяснений.

Форк дублирует процесс: он создает дочерний процесс, который почти идентичен родительскому процессу (наиболее очевидное отличие состоит в том, что новый процесс имеет другой идентификатор процесса). В частности, fork (концептуально) должен копировать всю память родительского процесса.

Поскольку это довольно дорого, vfork был изобретен для обработки общего особого случая, когда копия не нужна. Часто первое, что делает дочерний процесс, - это загружает новый образ программы, вот что происходит:

if (fork()) {
    # parent process …
} else {
    # child process (with a new copy of the process memory)
    execve("/bin/sh", …);  # discard the process memory
}

В execveзагружает вызов новый исполняемый файл программы, и это заменяет код и данные процесса памяти кодом нового исполняемого файла и свежей памяти данных. Таким образом, вся копия памяти, созданная ею, forkбыла совершенно даром.

Таким образом, vforkвызов был изобретен. Это не делает копию памяти. Поэтому vforkэто дешево, но сложно в использовании, так как вы должны быть уверены, что не обращаетесь ни к какому стеку или кучи процесса в дочернем процессе. Обратите внимание, что даже чтение может быть проблемой, потому что родительский процесс продолжает выполняться. Например, этот код не работает (он может работать, а может и не работать, в зависимости от того, получает ли ребенок или родитель первый временной интервал):

if (vfork()) {
    # parent process
    cmd = NULL; # modify the only copy of cmd
} else {
    # child process
    execve("/bin/sh", "sh", "-c", cmd, (char*)NULL);  # read the only copy of cmd
}

Со времени изобретения vfork были изобретены лучшие оптимизации. В большинстве современных систем, включая Linux, используется форма копирования при записи , при которой страницы в памяти процесса копируются не во время forkвызова, а позже, когда родительский или дочерний объект впервые записывает страницу. То есть каждая страница начинается как общая и остается общей до тех пор, пока какой-либо процесс не запишет на эту страницу; процесс, который пишет, получает новую физическую страницу (с тем же виртуальным адресом). Копирование при записи делает vfork в основном бесполезным, поскольку forkв тех случаях, когда vforkего можно было бы использовать, копирование не производится .

Linux сохраняет vfork. forkСистемный вызов должен еще сделать копию виртуальной таблицы процесса памяти, даже если он не копирует фактическую память; vforkдаже не нужно этого делать. Улучшение производительности незначительно в большинстве приложений.


1
Спасибо за этот блестящий ответ. Выполняя fork (), ребенок в любом случае получит новый идентификатор процесса и связанное с ним виртуальное пространство, тогда почему он все еще должен делать копию таблицы виртуальной памяти процесса? Мне не ясно в этой части.
Сен

@Sen: forkнеобходимо создать отдельное отображение виртуальной памяти, чтобы последующие копии при записи влияли только на один из двух процессов.
Жиль "ТАК - прекрати быть злым"

Вы уверены, что родительский процесс запущен?
Qbolec

2

fork()И vfork()системные вызовы различны.

fork()Системный вызов генерирует два идентичных процессы с отдельной памятью. vfork()Системный вызов генерирует два процесса , которые разделяют ту же память.

С vfork()родителем будет ждать, пока ребенок кончает. Родитель наследует от переменных, которые разделяет программа. Таким образом, после вызова дочернего элемента все переменные, измененные внутри дочернего элемента, все равно будут изменены внутри родительского элемента.

Для получения дополнительной информации нажмите здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.