Отношения между родителями и детьми и наследование в C - PullRequest
8 голосов
/ 16 февраля 2011

Я совершенно новичок с C.

  1. Какие элементы процесса наследуются в дочернем процессе, созданном с использованием fork();?

  2. Чем элементы процесса отличаются от родительского процесса?

Ответы [ 5 ]

15 голосов
/ 16 февраля 2011

Это не имеет ничего общего с C, скорее с fork(), который является системным вызовом POSIX (и я думаю, что он может вести себя по-разному в разных системах).

Я бы посоветовал вам прочитать fork руководство , которое действительно ясно об этом:

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

  • У дочернего элемента есть собственный уникальный идентификатор процесса, и этот PID не совпадает с идентификатором какой-либо существующей группы процессов (setpgid (2)).

  • Идентификатор родительского процесса дочернего процесса совпадает с идентификатором родительского процесса.

  • Ребенок не наследует блокировки памяти своего родителя (mlock (2), mlockall (2)).

  • Использование ресурсов процесса (getrusage (2)) и счетчики времени ЦП (times (2)) сбрасываются на ноль у дочернего элемента.

  • Дочерний набор ожидающих сигналов изначально пуст (sigpending (2)).

  • Дочерний объект не наследует настройки семафора от своего родителя (semop (2)).

  • Ребенок не наследует блокировки записи от своего родителя (fcntl (2)).

  • Ребенок не наследует таймеры от своего родителя (setitimer (2), alarm (2), timer_create (2)).

  • Дочерний объект не наследует невыполненные асинхронные операции ввода-вывода от своего родителя (aio_read (3), aio_write (3)) и не наследует любые контексты асинхронного ввода-вывода от его родителя (см. io_setup (2)).

Все атрибуты процесса в предыдущем списке указаны в POSIX.1-2001. Родитель и ребенок также различаются по следующие специфичные для Linux атрибуты процесса:

  • Дочерний объект не наследует уведомления об изменении каталога (dnotify) от своего родительского элемента (см. Описание F_NOTIFY в fcntl (2)).

  • Параметр prctl (2) PR_SET_PDEATHSIG сбрасывается, так что дочерний элемент не получает сигнал, когда его родитель заканчивается.

  • Отображения памяти, помеченные флагом madvise (2) MADV_DONTFORK, не наследуются через fork().

  • Сигнал завершения ребенка всегда равен SIGCHLD (см. clone (2)).

Обратите внимание на следующие дополнительные пункты:

  • Дочерний процесс создается с одним потоком, который называется fork(). Все виртуальное адресное пространство родителя реплицируется у ребенка, в том числе состояния мьютексов, состояние переменные и другие объекты pthreads; использование pthread_atfork (3) может быть полезно для решения проблем, которые это может вызвать.

  • Ребенок наследует копии набора родительских дескрипторов открытого файла. Каждый дескриптор файла в дочернем элементе ссылается на один и тот же открытый описание файла (см. open (2)) в качестве соответствующего дескриптора файла в родительском. Это означает, что два дескриптора совместно используют открытый файл флаги состояния, текущее смещение файла и управляемые сигналом атрибуты ввода / вывода (см. описание F_SETOWN и F_SETSIG в fcntl (2)).

  • Ребенок наследует копии набора родительских дескрипторов очереди сообщений (см. mq_overview (7)). Каждый дескриптор у ребенка ссылается на то же описание открытой очереди сообщений, что и соответствующее дескриптор в родительском. Это означает, что два дескриптора разделяют те же флаги (mq_flags).

  • Дочерний объект наследует копии набора родительских потоков открытых каталогов (см. opendir (3)). POSIX.1-2001 говорит, что соответствующий потоки каталога в родительском и дочернем элементах могут совместно использовать каталог позиционирование потока; в Linux / glibc их нет.

Если вас интересует Linux, вам также следует проверить системный вызов clone, который позволит вам с большей точностью указать, что вы хотите.

5 голосов
/ 16 февраля 2011

Страница man fork (2) в вашей системе (man fork) должна дать вам более подробную информацию, но обычно дочерний объект наследует только список родительских файловых дескрипторов, включая открытые файлы, сокеты и дескрипторы процессов.

Из справочной страницы моей системы (Mac OS X 10.6.6):

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

2 голосов
/ 16 февраля 2011
1 голос
/ 16 февраля 2011

В C. нет объектно-ориентированного наследования.

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

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

0 голосов
/ 16 февраля 2011

Единственное, что дочерний элемент отличается от своего родителя - это

PPID, т.е. идентификатор родительского процесса и

идентификатор процесса PID .

И когда дело доходит до подобия, дочерний процесс наследует таблицу FILE DESCRIPTOR своего родителя, поэтому вы видите, что всегда заняты три FILE DESCRIPTORS дочернего элемента, которые соответствуют STDIN, STDOUT и STDERR .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...