Разница между fork (), vfork (), exec () и clone()
Я искал, чтобы найти разницу между этими четырьмя на Google, и я ожидал, что там будет огромное количество информации об этом, но на самом деле не было никакого твердого сравнения между четырьмя вызовами.
Я пытаюсь составить базовый взглядом посмотреть на различия между этими системными вызовами и вот что я получил. Вся эта информация верна/я пропустил что-нибудь важное ?
Fork : вызов вилки в основном делает дубликат текущего процесса, идентичного почти во всех отношениях (не все копируется, например, ограничения ресурсов в некоторых реализациях, но идея состоит в том, чтобы создать как можно более близкую копию).
новый процесс (ребенок) получает другой идентификатор процесса (PID) и идентификатор старого процесса (родителя) в качестве его родителя по PID (идентификатор). Поскольку два процесса теперь работают точно с одним и тем же кодом, они могут сказать, что есть что по коду возврата fork-ребенок получает 0, родитель получает PID ребенка. Это все, конечно, предполагая, что вызов fork работает - если нет, то дочерний элемент не создается, и родитель получает код ошибки.
Vfork: основное различие между vfork и fork заключается в том, что при создании нового процесса с помощью vfork () родительский процесс временно приостанавливается, а дочерний процесс может занимать адресное пространство родителя. Это странное положение дел продолжается до тех пор, пока дочерний процесс не завершится или не вызовет execve(), после чего родитель
процесс продолжается.
это означает, что дочерний процесс vfork () должен быть осторожным, чтобы избежать неожиданного изменения переменных родительского процесса. В частности, дочерний процесс не должен возвращаться из функции, содержащей вызов vfork (), и он не должен вызывать exit () (если ему нужно выйти, он должен использовать _exit (); фактически, это также верно для дочернего элемента обычной вилки ()).
Exec : вызов exec-это способ в основном заменить весь текущий процесс с новой программой. Он загружает программу в текущее пространство процесса и запускает ее из точки входа. exec () заменяет текущий процесс на исполняемый файл, на который указывает функция. Управление никогда не возвращается к исходной программе, если нет ошибки exec ().
Clone : Clone, как fork, создает новый процесс. В отличие от fork, эти вызовы позволяют дочернему процессу совместно использовать части контекста его выполнения с вызывающим процессом, такие как пространство памяти, таблица файловые дескрипторы и таблица обработчиков сигналов.
когда дочерний процесс создается с помощью clone, он выполняет функцию application fn (arg). (Это отличается от fork, где выполнение продолжается в дочернем элементе с точки исходного вызова fork.) Аргумент fn является указателем на функцию, которая вызывается дочерним процессом в начале его выполнения. Аргумент arg передается в функцию fn.
когда приложение функции fn(arg) возвращает, дочерний процесс завершается. Целое число, возвращаемое fn, является кодом выхода для дочернего процесса. Дочерний процесс также может завершиться явным вызовом exit (2) или после получения фатального сигнала.
информация, полученная форма :
- различия между вилкой и старпома
- http://www.allinterview.com/showanswers/59616.html
- http://www.unixguide.net/unix/programming/1.1.2.shtml
- http://linux.about.com/library/cmd/blcmdl2_clone.htm
Спасибо, что нашли время, чтобы прочитать это ! :)
5 ответов:
vfork()это устаревшая оптимизация. Перед хорошим управлением памятью,fork()сделан полной копией памяти родителя, так что это было довольно дорого. так как во многих случаях afork()следовалexec(), который отбрасывает текущую карту памяти и создает новую, это были ненужные расходы. В наши дни,fork()не копирует память; он просто установлен как "копировать при записи", поэтомуfork()+exec()так же эффективно, какvfork()+exec().
clone()- это системный вызов, используемыйfork(). с некоторыми параметрами он создает новый процесс,с другими-поток. разница между ними заключается только в том, какие структуры данных (пространство памяти, состояние процессора, стек, PID, открытые файлы и т. д.) являются общими или нет.
execve()заменяет текущий исполняемый образ другим, загруженным из исполняемого файла.fork()создает дочерний процесс.vfork()является исторической оптимизированной версиейfork(), предназначенного дляexecve()вызывается непосредственно послеfork(). Оказалось, что он хорошо работает в системах без MMU (гдеfork()не может работать эффективно) и когдаfork()ing процессы с огромным объемом памяти для запуска небольшой программы (думаю, что в JavaRuntime.exec()). POSIX стандартизировалposix_spawn()чтобы заменить эти последние два более современных использованияvfork().posix_spawn()не эквивалентноfork()/execve(), а также позволяет некоторые FD жонглирование между ними. Он должен заменитьfork()/execve(), главным образом для платформ non-MMU.pthread_create()создает новый поток.clone()- это специфичный для Linux вызов, который может быть использован для реализации чего-либо изfork()topthread_create(). Это дает много контроля. Вдохновленный наrfork().rfork()это План-9 конкретного вызова. Предполагается, что это общий вызов, позволяющий несколько степеней совместного использования между полными процессами и потоками.
fork()- создает новый дочерний процесс, который является полной копией родительского процесса. Дочерние и родительские процессы используют разные виртуальные адресные пространства, которые изначально заполняются одними и теми же страницами памяти. Затем, по мере выполнения обоих процессов, виртуальные адресные пространства начинают отличаться все больше и больше, потому что операционная система выполняет ленивое копирование страниц памяти, которые записываются любым из этих двух процессов и назначает независимые копии измененные страницы памяти для каждого процесса. Этот метод называется Copy-On-Write (COW).vfork()- создает новый дочерний процесс, который является" быстрой " копией родительского процесса. В отличие от системного вызоваfork(), дочерние и родительские процессы используют одно и то же виртуальное адресное пространство. Заметьте! Используя одно и то же виртуальное адресное пространство, как родитель, так и потомок используют один и тот же стек, указатель стека и указатель инструкции, как в случае классическогоfork()! Чтобы предотвратить нежелательные интерференция между родителем и потомком, которые используют один и тот же стек, выполнение родительского процесса замораживается до тех пор, пока ребенок не вызовет либоexec()(создание нового виртуального адресного пространства и переход к другому стеку) или_exit()(завершение выполнения процесса).vfork()это оптимизацияfork()для модели" fork-and-exec". Это может быть выполнено в 4-5 раз быстрее, чемfork(), потому что в отличие отfork()(даже с коровой в уме), реализация
fork (), vfork () и clone () все вызывают do_fork () для выполнения реальной работы, но с разными параметрами.
asmlinkage int sys_fork(struct pt_regs regs) { return do_fork(SIGCHLD, regs.esp, ®s, 0); } asmlinkage int sys_clone(struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; clone_flags = regs.ebx; newsp = regs.ecx; if (!newsp) newsp = regs.esp; return do_fork(clone_flags, newsp, ®s, 0); } asmlinkage int sys_vfork(struct pt_regs regs) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0); } #define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ #define CLONE_VM 0x00000100 /* set if VM shared between processes */ SIGCHLD means the child should send this signal to its father when exit.для fork у ребенка и отца есть независимая таблица страниц VM, но поскольку эффективность, fork не будет действительно копировать какие-либо страницы, он просто устанавливает все записываемые страницы только для чтения для дочернего процесса. Поэтому, когда дочерний процесс хочет написать что-то на этой странице, происходит исключение страницы, и ядро выделит новую страницу, клонированную со старой страницы с помощью write разрешение. Это называется "копирование при записи".
для vfork, виртуальная память точно ребенком и отцом---только из-за этого, отец и ребенок не могут бодрствовать одновременно, так как они будут влиять друг на друга. Таким образом, отец будет спать в конце "do_fork()" и просыпаться, когда ребенок вызывает exit() или execve() с тех пор он будет владеть новой таблицей страниц. Вот код (в do_fork ()), что отец спит.
if ((clone_flags & CLONE_VFORK) && (retval > 0)) down(&sem); return retval;вот код (в mm_release () вызывается exit () и execve ()) которые будят отца.
up(tsk->p_opptr->vfork_sem);для sys_clone (), он является более гибким, так как вы можете ввести любые clone_flags к нему. Поэтому pthread_create () вызывает этот системный вызов со многими clone_flags:
int clone_flags = (CLONE_VM / CLONE_FS | CLONE_FILES | CLONE_SIGNAL | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID / CLONE_SYSVSEM);
сводка: fork (), vfork () и clone () будут создавать дочерние процессы с различным монтированием общего ресурса с отцовским процессом. Мы также можем сказать, что vfork() и clone () могут создавать потоки (на самом деле это процессы, поскольку они имеют независимую task_struct), поскольку они совместно используют таблицу страниц VM с процессом отца.
в fork (), либо дочерний или родительский процесс будет выполняться на основе выбора процессора.. Но в vfork (), конечно, ребенок будет выполнять в первую очередь. после того, как ребенок прекращен, родитель выполнит.
Comments