2015-09-20 3 views
1

В настоящее время я пытаюсь узнать о fork() и процессах вообще.Fork() не возвращает id> 0 в родительском процессе

У меня есть задача выполнить fork() определенное количество раз - n - которое пользователь может ввести. Кроме того, я должен использовать waitpid(), чтобы дождаться завершения моего процесса. Каждый процесс должен возвращать случайное число Разногласия между 1 и 6.

Вот мой код до сих пор:

#include <time.h> 
#include <stdlib.h> 
#include <stdio.h> 

int main(){ 

    int n,i; 
    int *returnvalue; 
    int pid; 
    int waitingID; 

    time_t t; 
    srand((unsigned)time(&t)); 

    printf("How many processes to start?\n"); 
    scanf("%d",&n); 

    for(i=0; i < n; i++){ 
    pid = fork(); 
    if(pid==0){ 
     printf("I am %d, from iteration %d\n",getpid(), i); 
    } 
    else if(pid > 0){ 
     waitingID = waitpid(pid, returnvalue, 0); 
     printf("Return-value of %d is: %d\n", waitingID, *returnvalue); 
    } 
    else{ 
     printf("A problem occured."); 
    } 
    } 

    return rand()%6; 
} 

Ниже приведен пример вывода текущей программы:

How many processes to start? 
5 
I am 6449, from iteration 0 
I am 6450, from iteration 1 
I am 6451, from iteration 2 
I am 6452, from iteration 3 
I am 6453, from iteration 4 
Segmentation fault (core dumped) 

Как вы можете видеть, у меня есть несколько проблем:

else if (pid>0) не называется вообще. Поэтому ожидание не происходит. Разве это не должно быть вызвано в каждой вилке, для соответствующего родительского процесса?

Кроме того, как только последняя итерация закончится и она вернется к возврату, я получаю эту ошибку с разделением (core dumped).

Я потерялся прямо сейчас. Я не могу понять, где моя ошибка.

+0

'fork()' не возвращает 'int' - он возвращает' pid_t'. См. Http://linux.die.net/man/2/fork. В то время как конкретная реализация может определять 'pid_t' как' int', это не означает, что 'pid_t' ** является **' int'. –

ответ

3
int *returnvalue; 

Это просто указатель к int, но не указывая нигде определено, так это:

waitingID = waitpid(pid, returnvalue, 0); 

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

Простая вещь, чтобы сделать, вместо того, чтобы определять указатель, определить фактическую int переменную:

int returnvalue; 

и передать указатель на эту переменную:

waitingID = waitpid(pid, &returnvalue, 0); 
+0

Я вижу это сейчас! Как я мог не заметить этого ... Это было долгое время без базового C ... – Sossenbinder

1

Вы не получите никакого вывода для родительского случая, потому что родительский процесс waitpid вызывает ошибку сегментации. returnvalue - любой неинициализированный указатель. Вам необходимо сделать это:

int returnvalue; 
... 
pid = fork(); 
if(pid==0){ 
    printf("I am %d, from iteration %d\n",getpid(), i); 
} 
else if(pid > 0){ 
    waitingID = waitpid(pid, &returnvalue, 0); 
    printf("Return-value of %d is: %d\n", waitingID, returnvalue); 
} 

Но даже это не то, что вы хотите. Возвращаемое значение от waitpid не должно использоваться как есть. Вам нужно использовать макросы WIF, чтобы определить дочернее существо, а затем использовать макрос WEXITSTATUS, чтобы получить возвращаемое значение. Это пример со страницы человека:

if (WIFEXITED(status)) { 
    printf("exited, status=%d\n", WEXITSTATUS(status)); 
} else if (WIFSIGNALED(status)) { 
    printf("killed by signal %d\n", WTERMSIG(status)); 
} else if (WIFSTOPPED(status)) { 
    printf("stopped by signal %d\n", WSTOPSIG(status)); 
} else if (WIFCONTINUED(status)) { 
    printf("continued\n"); 
} 
+0

Ну, я бы сказал: 1.) нет, первая проблема возникает уже в 'waitpid()', пытающейся записать в любое случайное местоположение 'returnvalue', но 2.) хорошая добавленная рекомендация о том, как обрабатывать код состояния , –

+0

@FelixPalmen Ах, ты прав. «Printf» - это проблема, но перед этим «waitpid». – kaylum

+0

Исправлено сейчас. – kaylum

0

Функция waitpid пытается записать хранилище, на которое указывает returnvalue. В вашем коде returnvalue не был инициализирован и поэтому его значение не определено.

С waitpid пытается писать на неизвестный адрес, он вызывает сбой.

Один из способов смягчения этого, как предлагается другими, - использовать int returnvalue, а затем передать его адрес &returnvalue - waitpid. Этот способ, так как переменная returnvalue создана на стеке, ее адрес является общедоступным, и waitpid также может писать на него.

Еще одно значение, которое вы можете сделать, хотя и не очень эффективно - это позвонить malloc и дать указателю адрес (хранилище, которое будет создано в куче, в отличие от стека), чтобы вы могли пройти до waitpid. Но не забудьте позвонить по телефону free.

returnvalue = malloc(sizeof(int)); 
waitingID = waitpid(pid, returnvalue, 0); 
printf("Return-value of %d is: %d\n", waitingID, *returnvalue); 
free(returnvalue); 
Смежные вопросы