fork clone чем отличается

Русские Блоги

Подробное объяснение разницы между fork (), vfork () и clone ()

Четыре элемента процесса:

Конкретный процесс выглядит следующим образом:

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

По результатам операции видно, что два процесса отца и сына выполняются синхронно, фактически, без определенного порядка.

vfork()

Vfork создает не реальный процесс, а поток, потому что ему не хватает обычных элементов (4), независимых ресурсов памяти, см. Следующую программу:

По результатам операции мы видим, что родительский процесс всегда ожидает завершения дочернего процесса, прежде чем продолжить.

clone

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

A в родительском элементе и сыне оба равны 10; это доказывает, что они разделяют переменную a,Это копия указателя, а не копия значения.

проблема:Разница между клоном и вилкой:

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

Источник

Русские Блоги

Подробное объяснение форка, вфорка и клона в Linux (разница и связь)

Поделитесь учебником по искусственному интеллекту моего учителя! Нулевой фундамент, легко понять!http://blog.csdn.net/jiangjunshow

Вы также можете перепечатать эту статью. Делитесь знаниями, приносите пользу людям и осознайте великое омоложение нашей китайской нации!

fork,vfork,clone

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

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

Из результатов выполнения видно, что процессы отца и сына имеют разные pids, а ресурсы стека и данных полностью копируются.

Дочерний процесс изменил значение count, в то время как количество в родительском процессе не изменилось.

Адрес (виртуальный адрес) дочернего процесса и количество родительских процессов совпадают (обратите внимание, что они сопоставлены с разными физическими адресами в ядре)

При написании копии

Некоторые люди думают, что такое большое количество копий приведет к слишком низкой эффективности выполнения. Фактически, в процессе репликации Linux использует стратегию копирования при записи.

Дочерний процесс копирует task_struct родительского процесса, пространство системного стека и таблицу страниц, что означает, что перед выполнением программы count ++ дочерний процесс и счетчик родительского процесса находились в одной и той же памяти. Когда дочерний процесс изменяет переменную (то есть, переменная записывается), для соответствующей страницы будет создана новая копия с помощью copy_on_write.

Поэтому, когда мы выполняем ++ count, тогда дочерний процесс создает новую страницу для копирования содержимого исходной страницы. Копирование основных ресурсов является необходимым и эффективным. Все выглядит так, как будто независимое пространство хранения родительского процесса также копируется снова.

Копировать (Copy-на-записи) записываемогоЭто стратегия оптимизации, используемая в области программирования. Основная идея заключается в том, что если несколько абонентов запрашивают один и тот же ресурс одновременно, они совместно получат один и тот же индикатор, указывающий на один и тот же ресурс, и система не будет в действительности реплицироваться, пока вызывающая сторона не попытается изменить ресурс. Личная копия предоставляется вызывающей стороне для предотвращения непосредственного обнаружения измененного ресурса, и этот процесс прозрачен только для других вызовов. Основным преимуществом этого подхода является то, что если вызывающая сторона не изменяет ресурс, личная копия не создается.

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

Выделите фреймы страниц для таблицы страниц дочернего процесса

Выделите фреймы страниц для страниц дочерних процессов

Инициализировать таблицу страниц дочернего процесса

Скопируйте страницу родительского процесса на соответствующую страницу дочернего процесса

Этот метод создания адресного пространства включает много обращений к памяти, использует много циклов ЦП и полностью уничтожает содержимое кэша. В большинстве случаев это часто не имеет смысла, поскольку многие дочерние процессы начинают свое выполнение с загрузки новой программы, которая полностью отбрасывает унаследованное адресное пространство.

Текущее ядро ​​Linux использует более эффективный метод, называемый Copy On Write (COW). Идея довольно проста: родительский и дочерний процессы совместно используют фрейм страницы вместо копирования фрейма страницы. Тем не менее, пока рамки страницы являются общими, они не могут быть изменены, то есть рамки страницы защищены. Независимо от того, когда родительский процесс или дочерний процесс пытается записать общий фрейм страницы, возникает исключение, тогда ядро ​​копирует страницу в новый фрейм страницы и помечает ее как доступную для записи. Исходный фрейм страницы по-прежнему защищен от записи: когда другие процессы пытаются писать, ядро ​​проверяет, является ли процесс записи единственным владельцем фрейма страницы, и, если это так, помечает фрейм страницы как доступный для записи.

Когда процесс A использует системный вызов fork для создания дочернего процесса B, поскольку дочерний процесс B фактически является копией родительского процесса A,

Следовательно, он будет иметь те же физические страницы, что и родительский процесс. Чтобы сэкономить память и ускорить скорость создания, функция fork () позволит дочернему процессу B совместно использовать физические страницы родительского процесса A только для чтения. В то же время родительский процесс A Права доступа к странице также установлены только для чтения.

Таким образом, когда родительский процесс A или дочерний процесс B выполняют операцию записи на этих общих физических страницах, будет сгенерировано прерывание исключения из-за сбоя страницы (page_fault int14). В это время ЦП выполнит функцию обработки исключений do_wp_page (), предоставленную системой. Разрешите это исключение.

do_wp_page () отменит совместное использование физической страницы, вызвавшей ненормальное прерывание записи, скопирует новую физическую страницу для процесса записи, чтобы у родительского процесса A и дочернего процесса B была физическая страница с одинаковым содержимым. Наконец, из исключения Когда функция обработки вернется, ЦПУ повторно выполнит инструкцию операции записи, которая только что вызвала исключение, так что процесс продолжит выполняться.

vfork

Если простой метод vfork () для fork более популярен, то структура виртуального адресного пространства дочернего процесса не создается ядром, а виртуальное пространство родительского процесса используется совместно. Конечно, этот подход разделяет физический родительский процесс. пространство

Дочерний процесс, созданный vfork, также приведет к зависанию родительского процесса, если только дочерний процесс exit или execve не вызовет родительский процесс.

Дочерний процесс, созданный vfok, совместно использует всю память родительского процесса, включая адрес стека, пока дочерний процесс не использует execve для запуска нового приложения.

Дочерний процесс, созданный vfork, не должен использовать return для возврата к вызывающей стороне или использовать exit () для выхода, но он может использовать функцию _exit () для выхода

Если мы используем return для выхода, вы обнаружите, что программа поймана в хаотически повторяющееся состояние vfork

Мы обнаружим, что дочерний процесс vfork возвращается в место вызова после использования return, поэтому родительский процесс создает новый процесс vfork,

Решением этой проблемы является не использование возврата в процессе, а использование вместо этого выхода или _exit

вилка и вфорк

Отличия и связи

Использование vfork () аналогично fork (). Но есть и различия. Конкретные различия сводятся к следующим 3 пунктам

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

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

vfork () гарантирует, что дочерний процесс запускается первым, а родительский процесс может быть запланирован для запуска только после того, как он вызовет exec или _exit. Если в
Перед вызовом этих двух функций дочерний процесс зависит от дальнейших действий родительского процесса, которые вызовут взаимоблокировку.

Перед вызовом exec или _exit данные с родительским процессом являются общими, и родительский процесс может быть запланирован для запуска после того, как он вызовет exec или _exit. Если дочерний процесс зависит от дальнейших действий родительского процесса перед вызовом этих двух функций, это вызовет взаимоблокировку. Когда значение переменной в сегменте общих данных необходимо изменить, родительский процесс копируется

vfork используется для создания нового процесса, и целью нового процесса является выполнение нового процесса. vfork и fork создают дочерний процесс, но он не полностью копирует адресное пространство родительского процесса в дочерний процесс и не будет копировать Таблица страниц. Поскольку дочерний процесс немедленно вызовет exec, адресное пространство не будет сохранено. Но перед вызовом exec или exit в дочернем процессе он запускается в пространстве родительского процесса.

Если дочерний процесс зависит от дальнейших действий родительского процесса при вызове vfork, это вызовет тупик. Это показывает, что этот системный вызов используется для запуска нового приложения. Во-вторых, дочерний процесс запускается непосредственно в пространстве стека родительского процесса после возврата vfork () и использует память и данные родительского процесса. Это означает, что дочерний процесс может уничтожить структуру данных или стек родительского процесса, что приведет к сбою.

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

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

Почему есть вфорк

Поскольку предыдущий ответвление при создании дочернего процесса создает новое адресное пространство, копирует ресурсы родительского процесса и часто выполняет вызовы exec в дочернем процессе, так что предыдущая работа по копированию будет напрасной, В этом случае умный человек придумал vfork. Дочерний процесс, который он породил, начал временно делить адресное пространство с родительским процессом (фактически это понятие потока), потому что в это время дочерний процесс выполняется в адресном пространстве родительского процесса. Таким образом, дочерний процесс не может писать,

Следовательно, vfork предназначен для выполнения системного вызова execve для загрузки новой программы сразу после создания дочернего процесса. Прежде чем дочерний процесс завершает работу или запускает новую программу, ядро ​​гарантирует, что родительский процесс заблокирован

После создания дочернего процесса с помощью функции vfork, дочерний процесс часто вызывает функцию exec для выполнения другой программы. Когда процесс вызывает функцию exec, процесс полностью заменяется новой программой, и новая программа запускается из своей основной функции. Выполнение, поскольку вызов exec не создает новый процесс, поэтому идентификатор процесса до и после не изменяется, exec просто заменяет сегмент текста, данных, кучи и стека текущего процесса другой новой программой.

clone

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

Для начала необходимо поговорить о структуре этой функции.
···c
int clone(int (fn)(void ), void *child_stack, int flags, void *arg);
···

знак смысл
CLONE_PARENT Родительский процесс созданного дочернего процесса является родительским процессом вызывающего, а новый процесс и процесс, который его создал, становятся «братьями» вместо «отец и сын»
CLONE_FS Дочерний процесс и родительский процесс совместно используют одну файловую систему, включая root, текущий каталог, umask
CLONE_FILES Дочерний процесс и родительский процесс используют одну и ту же таблицу дескрипторов файлов (дескриптор файлов)
CLONE_NEWNS Запустите дочерний процесс в новом пространстве имен, пространство имен описывает иерархию файлов процесса
CLONE_SIGHAND Дочерний процесс и родительский процесс используют одну и ту же таблицу обработчиков сигналов (обработчик сигналов)
CLONE_PTRACE Если родительский процесс отслеживается, дочерний процесс также отслеживается
CLONE_VFORK Родительский процесс приостанавливается до тех пор, пока дочерний процесс не освободит ресурсы виртуальной памяти.
CLONE_VM Дочерний процесс и родительский процесс выполняются в одном и том же пространстве памяти
CLONE_PID PID дочернего процесса совпадает с родительским процессом при его создании
CLONE_THREAD Добавлен в Linux 2.4 для поддержки стандарта потока POSIX, дочерний процесс и родительский процесс совместно используют одну группу потоков

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

клон, вилка, vfork разница и связь

Способ реализации

Процедуры обслуживания системных вызовов sys_clone, sys_fork и sys_vfork завершаются вызовом функции do_fork.

Параметры do_fork аналогичны параметрам системного вызова clone, но есть еще один reg (регистр пользовательского режима, сохраняемый стеком ядра). Фактически, другие параметры также принимаются regs

Конкретные параметры разные

fork, vfork:
Сервисная подпрограмма просто вызывает do_fork, но параметры слегка изменены
clone_flags:
sys_fork: SIGCHLD, 0, 0, NULL, NULL, 0
sys_vfork: CLONE_VFORK | CLONE_VM | SIGCHLD, 0, 0, NULL, NULL, 0
Пользовательский стек: все стеки родительского процесса.
parent_tidptr, child_ctidptr имеют значение NULL.

Источник

sergey vasin

The IT blog

GitHub: fork, clone и другие

Существующие репозитории чаще всего используются в двух случаях: для начала разработки своего проекта, причем не с нуля, а с использованием чьего-либо кода (Open Source!) или же для того, чтобы предложить внесение изменений в чей-либо уже существующий код. При этом во втором случае предполагается, что все изменения вы вносите в свой репозиторий, а к принятию их предлагаете уже в готовом виде.

Для того, чтобы получить в свое личное пользование какой-либо не принадлежащий вам репозиторий, нужно воспользоваться процессом с названием fork. То есть по сути мы создаем «вилку» в развитии чьего-либо проекта причем один из ее «зубцов» оказывается в вашем профиле.

Давайте в качестве примера предположим, что нас одолело нестерпимое желание помочь в локализации справочной информации для PowerShell и мы решили создать копию репозитория PowerShell/powerShell-Docs.ru-ru.

При этом мы также предполагаем, что у нас уже создан профиль на сайте github.com, и установлен и настроен Git Bash.

Для разветвления репозитория нам нужно найти его на сайте github.com, в нашем случае это будет https://github.com/PowerShell/powerShell-Docs.ru-ru и в правом верхнем углу нажать кнопку Fork. Через некоторое время в нашем профиле мы увидим копию нужного нам репозитория.

Clone

Так как работать с файлами репозитория мы, скорее всего, будем локально, с использованием каких-либо инструментов, например, Visual Studio Code, то стоит создать копию файлов уже, можно сказать, нашего репозитория на своем компьютере.

Этот процесс называется клонированием.

Для начала, нам нужен адрес, по которому расположен наш репозиторий. Для этого мы заходим в свой профиль на сайте github.com, переходим в нужный нам репозиторий и нажимаем кнопку Clone or download. В результате откроется окно со ссылкой на этот репозиторий, которую нам потребуется скопировать.

Далее мы открываем Git Bash, переходим в папку, где располагаются наши репозитории (хотя это может быть и новый, отведенный специально для целей хранения конкретного репозитория каталог) и вводим команду:

Syncing repos

Если вашей целью является участие в развитии определенного проекта, то, кроме внесения в него своих изменений (посредством механизма Pull Request), нам нужно получать также и изменения, внесенные другими участниками. Для возможности синхронизации изменений, произведенных в репозитории, с ответвлением которого мы работаем, нам нужно выполнить еще несколько действий.

Для начала нам нужно перейти на страницу оригинального репозитория, в нашем случае это https://github.com/PowerShell/powerShell-Docs.ru-ru, точно так же, как и в предыдущем случае, нажать кнопку Clone or download и скопировать предложенную ссылку в буфер обмена.

Далее нам потребуется вернуться в Git Bash и перейти в директорию репозитория, клонированного нами при помощи предыдущей команды.

Если мы введем команду:

то мы увидим что-то вроде:

Давайте добавим информацию об оригинальном репозитории при помощи команды:

Теперь, введя еще раз команду:

мы заметим, что вывод стал включать еще две строки:

Таким образом, мы создали запись об оригинальном репозитории, с которым мы будем синхронизироваться.

Теперь давайте обсудим несколько терминов.

clone — это расположенный на вашем компьютере репозиторий. В него вы будете вносить изменения и синхронизировать с вашим репозиторием (origin), расположенным на сайте github.com

remote — это репозитории, которые находятся на сайте github.com. То есть, те, что не являются локальными. К ним относится и origin, и upstream.

origin — это репозиторий, расположенный в вашем профиле и находящийся на сайте github.com. Это тот репозиторий, с которого вы делали клон для использования на локальном компьютере.

upstream — это оригинальный репозиторий, на основе которого посредством операции fork был создан репозиторий, расположенный в вашем профиле сайта github.com. Именно его изменения вы будете синхронизировать в расположенный на вашем локальном компьютере репозиторий.

Что тут интересно, так это то, что при синхронизации изменений из upstream, будет затронут только локальный, расположенный на вашем компьютере, репозиторий. Для того, чтобы синхронизированные изменения были также отражены в вашем репозитории на сайте github.com (origin), вам потребуется использовать команду git push. Но об этом чуть позже.

Итак, мы добавили информацию об upstream, теперь перейдем непостредственно к процессу синхронизации.

Для того, чтобы получить информацию о произведенных в upstream изменениях, введем следующую команду:

Далее нам нужно выбрать ветвь (branch) локального репозитория, в которую мы собираемся синхронизировать изменения. Обычно она соответствует ветви оригинального (upstream) репозитория. В случае репозитория powerShell-Docs.ru-ru на момент написания основной ветвью является live. Сделаем мы это следующей командой:

Теперь произведем синхронизацию изменений из ветви live оригинального репозитория:

Вместо использования команд fetch и merge по отдельности, мы можем воспользоваться командой pull, что приведет к тому же самому результату.

Branch

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

Для перехода к использованию созданной вами ветви введите следующую команду:

Для просмотра существующих локальных ветвей используется команда:

Для переименования ветви old_name в new_name команда:

Для удаления ветви branch_name:

Теперь вы можете начать вносить изменения в вашу локальную копию репозитория. После того, как вы внесли все необходимые правки и новые элементы кода, а также выполнили операцию commit, нужно передать внесенные изменения в ваш репозиторий на сайте github.com.

Используется для этого команда push. В качестве аргументов указываются удаленный репозиторий, куда будут передаваться изменения (например, origin) и имя ветви.

В нашем случае команда может выглядеть так:

Что касается имени ветви в вашем репозитории на сайте guthub.com, то оно не обязательно должно соответствовать имени локальной ветви. Например, чтобы передать содержимое ветви localbranch в ветвь remotebranch в вашем репозитории на сайте github.com, используйте следующую команду:

Чтобы удалить ветвь репозитория remotebranch на github.com, используйте команду:

Pull request

Для того, чтобы предложить владельцам оригинального репозитория внести ваши изменения и дополнения в свой проект, вам потребуется создать Pull request.

Для этого перейдите на страницу вашего репозитория на сайте github.com, при помощи кнопки Branch: выберите ветвь, содержимое которой вы хотели бы внести в оригинальный репозиторий и нажмите кнопку New pull request.

На открывшейся странице выберите репозиторий и ветвь куда бы вы хотели добавить ваш код (кнопки base fork: и base:), а также, при необходимости, измените репозиторий и ветвь, содержимое которых вы бы хотели предложить для добавления (кнопки head fork: и compare:), введите заголовок и описание вашего запроса и нажмите кнопку Create pull request.

Источник

Читайте также:  что делать если джинсы в талии большие лайфхаки
Сказочный портал