Как синхронизировать процессы внутри цикла while в c - PullRequest
1 голос
/ 19 апреля 2011

Я испытываю довольно дилемму:

У меня следующая структура программы:

char* input = (char *)malloc(sizeof(char));
input = "CONTINUE";

while(strcmp(input, "EXIT") != 0 )
{
    printf("%s", "prompt: ");
    scanf("%s", input);

    if( strcmp(input, "test") == 0 )
    {
        pid_t childPid;
        switch(childPid = fork())
        {
            case -1:
                printf("%s", "Error");
                break;
            case 0:
                foo(input);
                break;
        }
    }
    else if(/.../)
    {
    }
    else
    {
        input = "EXIT";
    }

}

void foo(char* input)
{
   printf("%s %s", "printing" input);
}

Так что проблема в том, что когда цикл выполняется, он выводит «prompt:» в первый раз, затем он снова печатает «prompt:», и, наконец, дочерний процесс из оператора if печатает свой вывод.

Это похоже на то, что дочерние процессы не синхронизированы или что-то в этом роде, и я не могу понять, что является причиной того, что дополнительная «подсказка:» печатается во второй раз. Это пример вывода:

prompt: test                  //typed "test"
prompt:                       //Where is this comming from?
printing test
prompt:                       //new iteration of loop expecting input

1 Ответ

3 голосов
/ 19 апреля 2011

fork() вызывает создание дочернего процесса в качестве точной копии родительского процесса, но также позволяет родительскому процессу продолжать выполнение.

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

Дочерний вызов foo (fork возвращает 0), но после этого ваш код просто прерывает оператор switch. После этой точки дочерний процесс следует точно так же, как и родительский, поэтому он выводит «prompt» и затем scanf.

То, что вы хотите сделать, это, вероятно, что-то более похожее на это:

childPid = fork();
if (childPid < 0)
{
    perror("fork()");
}
else if (childPid == 0)
{
    foo(input);
    exit(0); // terminate the child process
}
else
{
    waitpid(childPid, NULL, 0); // suspend the parent until the child exits
}

Поскольку вы printf пользуетесь обоими процессами, вы, вероятно, захотите приостановить родительский процесс до завершения дочернего процесса (используя waitpid). В противном случае «приглашение», скорее всего, будет напечатано до вывода из foo(). На некоторых платформах распечатки могут происходить одновременно, что приводит к смешанным символам или полностью искаженному выводу терминала.

...