Почему я получаю более одного SIGCHLD, когда звоню только один раз? - PullRequest
0 голосов
/ 02 декабря 2018

Я изучаю сигналы в Linux и пытаюсь понять механизмы процессов.Я написал этот код:

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

void filsFini(int sig){
  printf("The Child finished\n");
}

int main(){
  pid_t pid;
  system("clear");
  if((pid=fork())==0){
    printf("Child in a break\n");
    for(;;);
  }

  printf("The father %d \n",getpid());
  system("ps -lH");
  (void) signal(SIGCHLD,filsFini);
  printf("hit a button to end\n");
  getchar();
  kill(pid,SIGINT);
  system("ps -lH");
  waitpid(pid,NULL,0);
  system("ps -lH");
  return EXIT_SUCCESS;
}

в конце я получаю этот результат, у меня есть одна проблема, что printf("Child finished\n"); написано дважды, как я могу избежать этого?

Ответы [ 2 ]

0 голосов
/ 02 декабря 2018
  1. system("ps -lH"); также вызовет fork(), см. http://man7.org/linux/man-pages/man3/system.3.html

  2. Если вы хотите позвонить printf("Child finished\n"); только один раз, вы можете поймать SIGINT у ребенкаобработать и вывести его.

Может работать следующее code:

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

void handle_SIGINT(int sig) {
  printf("The Child finished\n");
  exit(EXIT_FAILURE);
}

int main(){

  signal(SIGINT, handle_SIGINT);

  pid_t pid;
  if ((pid=fork()) == 0) {
    printf("Child in a break\n");
    for(;;)
      ;
  }

  printf("The father %d \n", getpid());
  system("ps -lH");
  printf("hit a button to end\n");
  getchar();
  kill(pid, SIGINT);
  printf("\nbefore waitpid:\n");
  system("ps -lH");
  waitpid(pid, NULL, 0);
  printf("\nafter waitpid:\n");
  system("ps -lH");

  return EXIT_SUCCESS;
}
0 голосов
/ 02 декабря 2018

Вы создаете дополнительных детей при каждом вызове на system("ps -lH"), и вы также получаете SIGCHLD уведомления для них.К сожалению, нет никакого способа контролировать, для каких дочерних процессов вы получаете уведомления SIGCHLD.Это все или ничего.

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

(Природа "1014 *" "все или ничего" представляет собой серьезную проблему при написании более сложных программ, которым необходимо ожидать комбинаций переменных завершений дочерних процессов и асинхронных "События ввода / вывода, особенно если есть участвующие библиотеки, которые могут создавать дочерние процессы, о которых главный цикл событий не знает. Но не беспокойтесь об этом, пока не доберетесь.)

...