Intereting Posts
Вывод, который будет сохранен в файле с именем, аналогичным входному файлу Не удается смонтировать диски Как узнать, какая версия ядра будет содержать исправление ошибок? Использование переменной в регулярном выражении USB-модем не работает после установки какого-либо пакета Обновления системы в архиве linux с / boot в отдельном разделе? Как сканировать исходящие закрытые порты с nmap? скрипт iptables для блокировки всего интернет-доступа, за исключением желаемых приложений wget -k не конвертирует все ссылки Каково поведение по умолчанию для% install? Почему по умолчанию используется swappiness? Оптимальный способ отслеживания сеанса TTY, который блокирует ресурс? Как сбросить неизвестный пароль root, если проверка файловой системы прерывает последовательность запуска? Как установить Dolphin в качестве менеджера файлов по умолчанию в KDE? Есть ли бесплатная игра для игры в карты и настольная игра для Linux?

Вилка против клона на 2.6 ядра Linux

У меня есть путаница в отношении вилки и клона. Я видел это:

  • fork для процессов, а клон – для потоков

  • fork просто вызывает clone, clone используется для всех процессов и потоков

Являются ли эти данные точными? В чем отличие этих двух системных вызовов от ядра 2.6 Linux?

fork() был исходным системным вызовом UNIX. Его можно использовать только для создания новых процессов, а не для потоков. Кроме того, он переносимый.

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

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

clone() также используется для реализации функции pthread_create() POSIX для создания потоков.

Переносимые программы должны вызывать fork() и pthread_create() , а не clone() .

Похоже, что в Linux 2.6 есть две clone()

Существует системный вызов:

 int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ... /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ ); 

Это «clone ()», описанный с помощью man 2 clone .

Если вы прочтете эту страницу человека достаточно близко, вы увидите следующее:

 It is actually a library function layered on top of the underlying clone() system call. 

По-видимому, вы должны реализовать потоки, используя «библиотечную функцию», наложенную на системный вызов с одинаковым именем.

Я написал короткую программу:

 #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(int ac, char **av) { pid_t cpid; switch (cpid = fork()) { case 0: // Child process break; case -1: // Error break; default: // parent process break; } return 0; } 

Скомпилировал его с помощью: c99 -Wall -Wextra и запустил его под strace -f чтобы увидеть, что на самом деле делает система. Я получил это из strace на машине Linux 2.6.18 (процессор x86_64):

 20097 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4ee9213770) = 20098 20097 exit_group(0) = ? 20098 exit_group(0) 

В выводе strace нет вызова «fork». Вызов clone() который появляется в выводе strace имеет очень разные аргументы из man-page-clone. child_stack=0 поскольку первый аргумент отличается от int (*fn)(void *) .

Похоже, что системный вызов fork(2) реализован в терминах реального clone() , как и реализуется функция «library function» clone() . У реального clone() есть другой набор аргументов из man-page-clone.

Упрощенно, оба ваших явно противоречивых утверждения о fork() и clone() верны. Однако задействованный «клон» отличается.

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

По сути, для каждого «типа» информации, связанной с контекстом выполнения в ядре, clone() дает вам выбор сглаживания этой информации или ее копирование. Темы соответствуют сглаживанию, процессы соответствуют копированию. Указав промежуточные комбинации флагов на clone() , вы можете создавать странные вещи, которые не являются нитями или процессами. Обычно вы этого не должны делать, и я полагаю, что в ходе разработки ядра Linux возникли некоторые споры о том, должен ли он допускать такой общий механизм, как clone() .