2013-04-23 3 views
2

Это странный вопрос. У меня есть 2 разных программы: сервер и клиент.Избегайте зомби, когда отец находится в ожидании семафора.

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

for(;;){//infinite loop 
    wait(sem,1); //wait for new message 
    rc = msgctl(msgid, IPC_STAT, &qbuff); 
    seq_num++; 
    pid=fork(); //new process for take the message 
    if(!pid){ 
      if((msgrcv(msgid, &q, msgsz, 1,MSG_NOERROR))== -1) 
       perror("msgrcv error"); 
      else{ 
       pthread_mutex_lock(&mutex); //start critic sector 
       printf("\nthere is a prenotation\n"); 
       q.price=get_conf_value(q.kindof_service)+(q.priority*get_conf_value(3)); //costo = costo_visita + (priorità * costo_priorità) 
       q.turn=seq_num-q.priority; //assign turn 
       pthread_mutex_unlock(&mutex); //end critic sector 
       if(q.turn<0)q.turn=0; //controllo del turno che non sia minore di 0 
       printf("---------------------------"); 
       printf("\nPrenotation number %i\npid caller: %i\npriorità: %i\n for %i\ncost %i\nturn %i\n",seq_num,q.clientId,q.priority, q.kindof_service ,q.price, q.turn); 
       printf("---------------------------\nPrenotation ok\n\n\n"); 
       } 
    printf("\nsuccess.\n"); 
    exit(1); //close children process 
    } 
    } 

Проблема заключается в том, что, таким образом, отец оставить так много зомби. Если я добавлю

 else{//i am the father 
     waitpid(pid, 0, 0); 
    } 

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

Но без waitpid проблема другая .. потому что после этого он начинает весь процесс, необходимый для получения всего сообщения, отец берет на себя управление и все еще ожидает другого сигнала от клиента (первое ожидание (sem, 1)), оставляя так много зомбического процесса.

Я не знаю, если я объяснил это хорошо .. очень трудно в английском -_-

Итак, я хочу сервер, который, получив сигнал, вилка много много раз. любой ребенок принимает сообщение и делает кое-что, потом ребенок заканчивается. Тем временем сервер продолжает ждать нового входящего сообщения. Все без зомби :)

+0

Что вы хотите создать новый процесс для каждого получаемого вами сообщения или вы хотите, чтобы несколько процессов получали несколько сообщений одновременно? –

+0

Мне нужен новый процесс для каждого сообщения, которое я получаю! – ReTanica

+0

О, и я должен сказать, что я могу запускать клиент много раз, все togheter, затем одно mesasge, а затем запускать 3 клиента, отправляя 10 сообщений каждый – ReTanica

ответ

1

Один из способов пожаротушения и беззаботности, без необходимости беспокоиться о зомби, заключается в том, чтобы развить вилку дважды.

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

Так что вы можете сделать это с помощью вилки и вилки еще раз в дочернем процессе. Затем вы можете позволить ребенку выйти, что приведет к тому, что внук (где вы выполняете свою работу) наследуется init. Родительский процесс может сделать wait для ребенка (что не займет много времени, потому что ребенок сделал не что иное, как fork и exit). Когда внук выйдет, init будет автоматически wait для этого.

/* fire and forget */ 
int execute_detached(char **cmdline) 
{ 
    pid_t pid; 

    if((pid = fork()) < 0) { /* fork error */ 
    perror("fork"); 
    return 0; 
    } 
    else if(pid > 0) {  /* parent */ 
    waitpid(pid, NULL, 0); 
    return 1; 
    } 
    else {     /* child */ 
    if((pid = fork()) < 0) { /* fork error */ 
     perror("fork"); 
     return 0; 
    } 
    else if(pid > 0) {  /* child */ 
     /* make grand child an orphan */ 
     _exit(0); 
    } 
    else {     /* grand child */ 
     execvp(cmdline[0], cmdline); 
     perror("execvp"); 
     _exit(1); 
    } 
    } 
    return 0; 
}