C: fork () - Ребенок и Родитель не действуют, как ожидалось - PullRequest
0 голосов
/ 21 февраля 2019

Мой код ниже fork() это процесс, создающий свой дочерний элемент, они оба вызывают одну и ту же функцию, которая в основном будет иметь цикл.Внутри они спят в течение случайного количества секунд между 0 и 5, затем они печатают глупое сообщение, показывающее, какой проход завершен.Наконец, они печатают «выходящее» сообщение и уходят.

Проблема в том, что каждый раз, когда Дочерний печатает «выходящее» сообщение, Родитель (по-видимому) печатает одно и то же, даже если родитель все еще равен 1 или2 прохода до финиша.Когда Родитель заканчивает работу, он снова напечатает «выходящее» сообщение.Если родительский процесс завершается до дочернего процесса, он выводит сообщение «выход» по окончании и снова после дочернего.

Теперь, если я выйду или вернусь в предложении «дочерний элемент if» после выполнения моей функции,тогда родительское «выходящее» сообщение не печатается.Это наводит меня на мысль, что Ребенок печатает «выходящее» сообщение от имени Родителя.Итак, что заставляет родительское «выходящее» сообщение печататься дважды?

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

const int PASS = 5;
const int RANDLIMIT = 5;
int i = 0;

void doSomeWork(char *who);

int main(int argc, char *argv[])
{
  printf("Just started, I am: %d\n", (int) getpid());
  pid_t pid = fork();
  printf("fork returned: %d\n", (int) pid);
  srand((int) pid);

  if (pid < 0) {
    perror("fork failed");
  } else if (pid == 0) {
    doSomeWork("Child");
    // if I exit(0) or return(0) here, it behaves accordingly.
  }
  doSomeWork("Parent");
  return(0);
}

void doSomeWork(char *who)
{
  int control = 0;
  for(; i < PASS; i++){
    sleep(rand() % RANDLIMIT);
    printf("%s: Done pass #%d\n", who, i);
  }
  printf("%s: exiting...\n", who);
}

Дочерний, заканчивающий первым:

[root@centos ~]# ./fork3
Just started, I am: 18232
fork returned: 18233
fork returned: 0
Child: Done pass #0
Parent: Done pass #0
Child: Done pass #1
Child: Done pass #2
Child: Done pass #3
Parent: Done pass #1
Parent: Done pass #2
Child: Done pass #4
Child: exiting...
Parent: exiting...
Parent: Done pass #3
Parent: Done pass #4
Parent: exiting...

Родитель, заканчивающий первым:

[root@centos ~]# ./fork3
Just started, I am: 19507
fork returned: 19508
Parent: Done pass #0
Parent: Done pass #1
fork returned: 0
Child: Done pass #0
Parent: Done pass #2
Parent: Done pass #3
Child: Done pass #1
Child: Done pass #2
Child: Done pass #3
Parent: Done pass #4
Parent: exiting...
[root@centos ~]# Child: Done pass #4
Child: exiting...
Parent: exiting...

1 Ответ

0 голосов
/ 21 февраля 2019

Вы звоните doSomeWork("Parent") в и родителю и ребенку.Вот почему exit заставляет его работать - тогда дочерний процесс завершается прямо перед вызовом doSomeWork("Parent").

. Решение будет таким:

if (pid < 0) {
    perror("fork failed");
} else if (pid == 0) {
    doSomeWork("Child");
} else {
    doSomeWork("Parent");
}

И, конечно, помните, что оба процесса выполняются одновременно,таким образом, порядок выполнения непредсказуем (применяются обычные задачи многозадачности).

...