вилки в C - упражнение - PullRequest
       12

вилки в C - упражнение

15 голосов
/ 22 марта 2010

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

Вот идет:

main() {
 if (fork() == 0) {
  if (fork() == 0) {
   printf("3");
  }
  else if ((wait(NULL)) > 0) {
   printf("2");
  }
 }
 else {
  if (fork() == 0) {
   printf("1");
   exit(0);
  }
  if (fork() == 0) {
   printf("4");
  }
 }
 printf("0");
 return 0;
}

Возможные решения:

  1. 3201040
  2. 3104200
  3. 1040302
  4. 4321000
  5. 4030201
  6. 1403020

где 2, 5 и 6 - правильные ответы.

Прежде всего, не должно ли быть четыре ноля на выходе? Второе ... Как можно прийти к решению вообще? Я делал это на бумаге в течение почти часа, и я даже близко не понимаю, почему данное решение является более правильным, чем ложное (за исключением nr3, поскольку оно не может заканчиваться на 2, так как должен следовать 0).

Кто-нибудь с проверенными вилками, кто может дать хорошее объяснение?

EDIT:

Нашли здесь посмотрите на PDF-файлы 2009 года. Могут ли теперь люди перестать публиковать сообщения о том, что это домашнее задание, и действительно пытаются помочь? Если нет, пожалуйста, найдите другие темы, чтобы провести время. Спасибо!

Ответы [ 4 ]

10 голосов
/ 22 марта 2010

Я думаю, что должно быть 4 ноля, и это то, что я вижу, если я запускаю ваш код ...

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

----*----*----*----0----exit (return from main)
    |    |    |
    |    |    +----4----0----exit (return from main)
    |    |
    |    +----1----exit (explicitly)
    |
    +-----*----wait----2----0----exit (return from main)
          |
          +----3----0----exit (return from main)

Теперь легко увидеть, что из-за wait() вы должны увидеть 3, за которым через некоторое время следует 0, до , затем 2 и 0.

4 голосов
/ 22 марта 2010

В выводе только три нуля из-за оператора exit после того, как программа напечатает 1. Этот оператор немедленно завершает этот процесс. Ред .: Нет, на самом деле должно быть 4 нулями; Я упустил из виду оригинальный процесс. Понятия не имею, почему в ответе нет четырех нулей.

Что вы должны понимать в целом при анализе ответов на вопрос:

  1. Каждый раз, когда вы вызываете fork(), вы создаете новый процесс, и старый процесс также продолжается, оба из одной и той же точки
  2. Вы можете определить, находитесь ли вы в «старом процессе» или «новом процессе», проверив возвращаемое значение fork. Это будет 0 (false), если вы находитесь в новом процессе, и ненулевое (true), если вы находитесь в старом процессе.
  3. Вызов wait(NULL) приостановит выполнение текущего процесса до тех пор, пока один процессов, которые его разветвляют, не завершится.
  4. (самое важное). Операторы в разных процессах могут выполняться в любом порядке относительно друг друга. Но утверждения внутри одного процесса должны, конечно, оставаться последовательными.

Чтобы уточнить 4, представьте, что у вас есть два процесса, один из которых печатает «abc», а другой - «xyz». Вывод, такой как «abxcyz», «xaybcz» или «xyabcz», возможен, потому что последовательности abc и xyz отображаются в определенном порядке. Однако вывод «abzcxy» невозможен, поскольку z не может появиться до x, поскольку оба они происходят из одного и того же процесса, а операторы, которые их печатают, отображаются в другом порядке.

1 голос
/ 22 марта 2010

Они предполагают, что при вызове wait (NULL) будет выполнен весь форк 3. Это включает в себя печать «0» в конце этого разветвления. Таким образом, ответы 1 и 4 неверны, потому что они не имеют «0» перед «2».

А почему нет четырех нулей, я не знаю.

0 голосов
/ 22 марта 2010

Во-первых, варианты, которые вы должны выбрать, это , а не все возможные варианты вывода. Скорее, их всего несколько. Глядя на исходный код, есть несколько вещей, которые мы можем заметить, чтобы исключить возможности:

  1. Ветвь, которая печатает «1», затем делает exit(0), даже не печатая «0». Таким образом, на выходе ожидается только три 0. Также по этой причине последний символ должен быть 0 или 1.
  2. После второй развилки мы wait(NULL) для ребенка перед печатью "2". Это означает, что ожидаемый нами потомок всегда печатает 3, а затем 0, прежде чем мы напечатаем 2.

Это действительно единственные вещи, которые можно однозначно сказать об этой проблеме. Это означает, что любой правильный ответ должен заканчиваться на 0 или 1 и должен иметь как 3, так и 0 перед 2. Единственные ответы, отвечающие этим критериям, это 2, 5 и 6.

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