нет чередования в выводе, в то время как родитель и потомок пишут в стандартный вывод - PullRequest
0 голосов
/ 01 ноября 2018

Я пытался написать код, чтобы увидеть, как использовать fork для создания дочернего процесса. Поскольку дочерний объект наследует файловый объект и дескриптор от родительского, если и дочерний, и родительский записи пишут в стандартный вывод, в выходных данных должно быть чередование, если я правильно понимаю. В следующем коде, который я пишу, я объявляю две строки как родительской, так и дочерней, и записываю их в стандартный вывод. Что я наблюдаю, так это то, что на выходе нет чередования. Я что-то пропустил?

код:

#include <unistd.h>
#include <stdio.h> 
#include <stdlib.h>
#include <sys/wait.h>

int main() {
  pid_t return_value;
  pid_t wait_p;
  if ((return_value = fork()) != 0) {
     char pa[15]= "Hi from parent\n";
     char pa_2[18]= "Hello from pariii\n";
     write(1, pa, 15);
     write(1, pa_2, 18);
  } else {
     char c[17] = "Hello from child\n";
     char c_2[14] = "Hi from chiii\n";
     write(1, c , 17);
     write(1, c_2, 14);
  }
  exit(0);
}

Вывод на моей машине (Ubutun 18.04, соблюдайте gcc):

Hi from parent
Hello from pariii
Hello from child
Hi from chiii

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

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Системный вызов write является атомным ; то есть все это происходит одновременно. Нет возможности для чередования строк. Если вы сделаете вызов write из нескольких частей (например, напишите строку "Hi from ", а затем напишите строку "parent" или "child", а затем напишите новую строку), то вы, вероятно, увидите чередование , Когда вы write целое сообщение в виде одной строки, это никогда не произойдет.

Обратите внимание, что вызовы более высокого уровня, такие как printf или аналогичные, имеют более сложные правила буферизации и, следовательно, могут иметь другие правила.


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

Что касается того, почему он никогда не печатает одну строку из родительского, затем одну строку из дочернего, затем вторую строку из родительского, я бы предположил, что это связано со спецификой планировщика и записи в виртуальный терминал , Переключение контекста с одного процесса на другой стоит дорого; если write достаточно быстр, планировщик может сказать, что не должен этого делать. Возможно, если вы вместо этого записали на диск и позвонили sync между write s, чтобы убедиться, что (относительно медленный) диск действительно был задействован, он с большей вероятностью будет чередоваться. Или, возможно, нет; это действительно трудно предсказать. Если вы действительно хотите увидеть чередование, я бы написал по крайней мере несколько килобайт, по несколько раз, от родителя и ребенка; это было бы близко к определенному чередованию.

0 голосов
/ 01 ноября 2018

должно быть чередование на выходе

Нет, выход может быть чересстрочным. Или не может. Все зависит от планировщика или фазы луны.

...