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

Я пытаюсь повторить и изучить более сложные способы использования и варианты при разрезании деревьев с помощью вилок в джунглях 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;
}

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

  • 3201040
  • 3104200
  • 1040302
  • 4321000
  • 4030201
  • 1403020

где 2, 5 и 6 являются правильными ответами.

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

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

EDIT:

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

Ответы

Ответ 1

Я думаю, что должно быть 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.

Ответ 2

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

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

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

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

Ответ 3

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

Что касается того, почему нет четырех "0" , я не знаю.

Ответ 4

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

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

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