2017-10-01 6 views
2

J'essaie actuellement d'expérimenter des signaux en C en les utilisant pour contrôler un processus enfant créé avec la méthode fork(). Essentiellement, j'ai un processus fils exécutant la commande "yes" depuis le terminal Linux (cette commande imprime juste "y" et un retour à la ligne jusqu'à ce qu'il soit terminé). Je veux être en mesure de faire une pause/reprendre ce processus avec CTRL-Z. C'est ce que j'ai en ce moment:Utilisation de gestionnaires de signaux pour suspendre/reprendre un processus enfant

#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 
pid_t CHILD_PROCESS; 
pid_t PARENT_PROCESS; 
int isPaused; 
void pause_handler(int signo){ 
    if(!isPaused){ 
    printf("Ctrl-Z pressed. Pausing child.\n"); 
    isPaused = 1; 
    kill(CHILD_PROCESS,SIGSTOP); 
    } 
    else if(isPaused){ 
    printf("\nCtrl-Z pressed. Resuming child.\n"); 
    kill(CHILD_PROCESS,SIGCONT); 
    isPaused = 0; 
    } 
} 

int main(int argc, char** argv){ 
    pid_t pid; 
    PARENT_PROCESS = getpid(); 
    pid = fork(); 
    if(pid == 0){ 
    system("yes"); 
    } 
    isPaused = 0; 
    if(pid > 0){ 
    signal(SIGTSTP, SIG_IGN); 
    signal(SIGSTOP, SIG_IGN); 
    CHILD_PROCESS = pid; 
    while(1){ 
     if(signal(SIGTSTP,pause_handler) == SIG_ERR){ 
     printf("Signal Failure"); 
     } 
    } 
    } 
} 

Quand je cours, je peux obtenir «Ctrl-Z pressé enfant faire une pause. » pour imprimer à la console en appuyant sur CTRL-Z, et je peux obtenir "Ctrl-Z pressé .Reprise enfant." pour imprimer sur la console en appuyant à nouveau sur CTRL-Z. Cependant, il ne reprend pas réellement l'impression "y" encore et encore. Des idées sur la raison pour laquelle le processus de l'enfant ne reprend pas?

Répondre

3

Comme il se trouve, a system un appel implicite fourchette à l'intérieur, de sorte que le PID qui est stocké dans CHILD_PROCESS finit par ne pas être en fait le processus de l'enfant, et au lieu d'un intermédiaire.

De man 3 system:

The system() library function uses fork(2) to create a child process 
    that executes the shell command specified in command using execl(3) as 
    follows: 

     execl("/bin/sh", "sh", "-c", command, (char *) 0); 

    system() returns after the command has been completed. 

Donc, si nous remplaçons l'appel system("yes") avec execl("/bin/sh", "sh", "-c", "yes", NULL), puis nous évitons cette fourche supplémentaire et les fonctions du programme comme vous le souhaitez.


Le seul autre problème est que, par je remarque que je trouve on this post, en utilisant printf dans un gestionnaire de signaux est un comportement non défini. Pas un problème à se soucier ici, mais quelque chose à garder à l'esprit pour le code futur!

+1

Le Q & A «canonique» est [Comment éviter d'utiliser 'printf()' dans un gestionnaire de signal?] (Http://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in- a-signal-handler /) –