почему fork () возвращает все возможные выходы в этой комбинации?

Вопрос:

Мне нужно разъяснение / помощь в моем понимании выходных данных fork (). Я знаю, как программировать более подробный и крупный код на c с помощью fork () и использовать другие концепции, такие как pipe, ipc, thread (posix). Но я плохо разбираюсь в прогнозировании результатов возврата, поэтому я пытаюсь это понять. Я считаю, что мой случай 1 верен, но другие мои случаи неоднозначны или похожи на него, потому что я не совсем уверен в выводе fork () .

Я неплохо разбираюсь в выводе программ, я понимаю базовые алгоритмы, которые содержат цикл for, while, if / else, структуры данных, рекурсивные выводы.

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

Мой подход:

Первоначально у нас есть родительский процесс, запускающий p0, а затем pid разветвляет дочерний процесс.

Таким образом, все возможные выходные данные всегда будут содержать 0, потому что изначально num = 0 и перед первым оператором prinf () num не установлен на какое-либо другое число.

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

case 1: p0 печатает 02, потому что может быть случай, когда pid является родительским. Затем разветвленный дочерний процесс p1 выводит 01. Окончательный ответ будет 0201.

случай 2: p0 печатает 01, потому что может быть случай, когда pid является дочерним (является ли он дочерним по отношению к основному процессу ядра?). Затем разветвленный дочерний элемент p1 является родителем, поэтому он печатает 0102. Окончательный ответ будет 0102.

case 3: p0 печатает 00, поскольку pid не является дочерним или родительским. Затем разветвленный дочерний элемент p1 выводит 12, потому что он является дочерним и родительским одновременно. Окончательный ответ - 0012.

case 4: p0 печатает 00, поскольку он не является родительским или дочерним. Затем разветвленный дочерний процесс p1 выводит 21, потому что он может быть родителем и потомком одновременно. Окончательный ответ - 0021.

Код:

#include <stdio.h>
int num = 0 ;
int main(int argc, char *argv[])
{
  int pid ;
  pid = fork() ;

  printf("%d",num) ;

  if (pid == 0) {
    num = 1;
  } else if (pid > 0) {
    num = 2 ;
  }
  printf("%d",num) ;
}

Ответ: 0102 или 0012 или 0201 или 0021


person geforce    schedule 21.02.2015    source источник
comment
Вы не можете контролировать, когда и в каком порядке будет запускаться каждый из двух процессов. Если вы хотите, чтобы процессы работали в определенном порядке, вы должны использовать какую-то межпроцессную синхронизацию.   -  person Some programmer dude    schedule 21.02.2015
comment
родитель и ребенок мчатся на этом printf на stdout. Больше нечего.   -  person Red Alert    schedule 21.02.2015
comment
Да, но я пытаюсь понять, как найти шаблон всех возможных выходов, потому что это то, чего я не понимаю, потому что я могу случайным образом печатать числа, такие как 0120, но это не входит в «ответы».   -  person geforce    schedule 21.02.2015
comment
Прочтите Расширенное программирование Linux. В нем есть несколько глав, в которых объясняется fork, а также как и когда его использовать.   -  person Basile Starynkevitch    schedule 21.02.2015
comment
C, без учета циклов и прочего, в значительной степени является последовательным. Операторы выполняются сверху вниз в том порядке, в котором вы это запрограммировали. Таким образом, если код должен печатать число 0 перед 1 или 2, то число 0 никогда не будет напечатано после того, как вы напечатаете либо 1, либо 2. Это означает, что дело 0120 получить невозможно.   -  person Some programmer dude    schedule 21.02.2015


Ответы (2)


Я думаю, вы слишком усложняете это. Что происходит после fork(), так это то, что у вас выполняются два экземпляра (отец и сын), каждый из которых выполняет две операции вывода.

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

person Stefano Sanfilippo    schedule 21.02.2015
comment
будет ли 0120 возможным выходом? - person geforce; 21.02.2015
comment
Нет, потому что вы должны сохранять правильный порядок для каждого экземпляра: сначала 0, затем 1 или 2. 0120 мог быть 01 и 20 или 02 и 10, и оба не уважают это. - person Stefano Sanfilippo; 21.02.2015
comment
Когда вы говорите, что первые выходы должны быть 0, а затем 1 или 2. Означает ли это, что позиция 0 равна 0, тогда позиция 1 равна 1 или 2? Что, если позиция 1 равна 0, означает ли это, что fork () не удалось? - person geforce; 21.02.2015
comment
Нет, 0012 в порядке. Представьте, что два экземпляра работают в разных окнах: один будет выводить 01, а другой 02. Правильно? Теперь попробуйте чередовать два выхода: 0102, 0012 в порядке, но 0120 нет, потому что нет 0 после 1, 2 или 0 в отдельных выходах. - person Stefano Sanfilippo; 21.02.2015
comment
Я начинаю понимать, что родительский процесс всегда будет печатать 02, а дочерний процесс всегда будет печатать 01, поэтому комбинации вывода действительно происходят от чередования в основном? - person geforce; 21.02.2015
comment
Да, точно. Более того, если вы напечатали более одного символа на printf, выходные данные могли бы даже чередоваться на уровне символов, поэтому, если один процесс напечатал HELLO WORLD, а другой foo bar baz, вы могли бы получить HELfoo LObarW bazORLD в качестве вывода, если порядок двух Независимые выходы не меняются. - person Stefano Sanfilippo; 21.02.2015

Назовем родительский процесс A и дочерний процесс B. A всегда будет печатать 0, за которым следует 2. B всегда будет печатать 0, за которым следует 1. Время A относительно B не определено. Вывод из A может печататься до, с чередованием или после вывода из B.

Фактически существует шесть возможных результатов, как показано ниже. Однако вы увидите только четыре разных шаблона вывода, потому что вы не можете сказать, A или B напечатано первым, когда вывод начинается с 00.

AABB
0201

ABAB
0021

BAAB
0021

ABBA
0012

BABA
0012

BBAA
0102
person user3386109    schedule 21.02.2015
comment
В этом есть смысл, спасибо за разъяснение. Насколько я понимаю, я постараюсь изучить это и понять больше, поэтому я могу ответить позже, потому что я только сейчас понял, что это в основном зависит от чередования и времени. - person geforce; 21.02.2015
comment
Я проверю этот результат, который вы показали, и, если у меня будут вопросы, я оставлю комментарии - person geforce; 21.02.2015
comment
Итак, когда в шаблоне встречаются AA или BB, это означает, что нет ошибок или чередования, но когда возникает AB, BA, это означает, что есть сбой / ошибка и происходит чередование? - person geforce; 22.02.2015
comment
@geforce Процессы A и B выполняются независимо, но используют одно устройство вывода. На многоядерном процессоре A и B будут работать одновременно и будут соревноваться за генерацию вывода. Если A выиграет, вы увидите AABB. Если B выигрывает, то BBAA. Иногда время настолько близко, что выходы чередуются, и вы получаете что-то вроде ABAB. На одноядерном процессоре операционная система будет переключаться между A и B через равные промежутки времени. Таким образом, A может выводить 0, и ОС переключается на B, который выводит 0 1, а затем ОС переключается обратно на A, что приводит к ABBA. Никаких сбоев / ошибок не связано, это просто многозадачность. - person user3386109; 22.02.2015