Вы можете поместить разветвление в цикл и генерировать столько дочерних процессов, сколько вам нужно.
Я недавно сделал это на проекте.
for(nSon=0; nSon < nSonsAsked; nSon++) {
Log_Print("Setup son #%.2u ", nSon+1);
if((pid = fork()) == 0) {
/* Do child stuff init, like connect the pipes, close shared handles */
return iTMInChild(...); /* A specific function of the child work */
/* The life of the child should not go beyond that point, i.e. the loop is over
or else the child will spawn even more processes. */
}
else if(pid > 0) {
/* Father process stuff. Here I initialise an array with the pid of the forked */
/* processes, this way I can index with the number of processes.*/
pid[nSon] = pid;
}
else
return Err_Print(ERR_FORK_FAILED, "fork failed. errno=%d \"%s\"\n", errno, strerror(errno));
}
Log_Print () и Err_Print () являются внутренними функциями, но вполне очевидны, поэтому я позволяю им быть такими, как есть.
Есть один аспект с переменными, который необходимо объяснить. nSon
и nSonAsked
должны быть объявлены как глобальные переменные, а не как переменные стека. Таким образом, их ценность сохраняется в разветвленном процессе. Это означает, что переменная nSon
будет иметь разные значения в каждом из дочерних элементов. Это позволяет ему иметь более простую схему нумерации, чем номер ownpid()
.
Чтобы все было правильно, есть много деталей, чтобы понять это правильно. Вам нужно будет установить обработчики сигналов в родительском процессе для обнаружения смерти ребенка, так же как и наоборот (возможно только в Linux, другие Unix (по крайней мере, Solaris) не поддерживают родительские сигналы смерти).
Вы должны знать, что дескрипторы открытых файлов в родительском процессе также будут открыты у дочернего элемента после fork, и это будет тот же . Это открывает много проблем параллелизма, если вы не знаете об этом (решение использует dup()
и close()
в нужных местах).