#c #linux #process #fork
#c #linux #процесс #форк
Вопрос:
Я сталкиваюсь с настоящей дилеммой:
У меня есть следующая структура программы:
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:», и, наконец, дочерний процесс из инструкции if печатает свои выходные данные.
Похоже, что дочерние процессы не синхронизированы или что-то в этом роде, и я не могу понять, из-за чего это дополнительное «приглашение:» печатается во второй раз. Это пример вывода:
prompt: test //typed "test"
prompt: //Where is this comming from?
printing test
prompt: //new iteration of loop expecting input
Комментарии:
1. У вас тоже есть проблемы с переполнением буфера в вашем коде. Вы выделяете достаточно места для одного символа и ожидаете, что в него будут помещены строки из 4 букв. Не говоря уже о том, что scanf печально известен тем, что вызывает переполнение буфера.
2. @Tangrs для простоты примера я использовал scanf. Реальный код использует getline().
3. Однако проблема с переполнением буфера все еще существует. Прошло много времени.
Ответ №1:
fork()
приводит к созданию дочернего процесса как точной копии родительского, но также позволяет родительскому процессу продолжать выполнение.
Ваш код ничего не делает в родительском коде, когда он успешно порождает дочерний (fork возвращает число, большее 0, указывающее идентификатор дочернего процесса; этот возврат не обрабатывается вашим коммутатором). Таким образом, родительский сервер возвращается к началу цикла while и снова выводит «приглашение».
Дочерний элемент вызывает foo (fork возвращает 0), но после этого ваш код просто выполняет break из инструкции switch. После этого дочерний элемент следует точно такому же пути к коду, что и родительский, поэтому он также выводит «приглашение», а затем выполняет 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()
. На некоторых платформах распечатки могут выполняться одновременно, что приводит к смешанным символам или полностью искаженному выводу терминала.
Комментарии:
1. Спасибо! Я думал, что есть что-то вроде того, что могло бы это сделать. Я пытался использовать wait (3) в родительском, но это не сработало, так что … теперь я знаю, как это сделать правильно. Большое спасибо!