Вилки в 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.