2010-10-13 2 views
0

J'écris un programme pseudo-shell qui crée un enfant à partir d'un processus parent. Le processus parent attend que l'enfant termine avant de continuer. Mon code fourcheur ressemble à ceci:C - pseudo-shell et concurrence

if(fork()==0) 
{ 
    execvp(cmd, args); 
} 
else 
{ 
    int status = 0; 
    wait(&status); 
    printf("Child exited with status of %d\n", status); 
} 

Mais, je veux être en mesure d'analyser l'opérateur « & », de sorte que si un utilisateur, il entre à la fin d'une ligne de commande, le parent ne sera pas attendez l'enfant avant d'inviter l'utilisateur à une autre commande. J'ai ajouté du code pour gérer cela, mais je ne savais pas exactement si ça marchait bien. Est-ce que cela ressemblerait à quelque chose comme:

if(fork()==0) 
{ 
    execvp(cmd, args); 
} 
else 
{ 
    if(andOp = 1) //boolean to keep track of if '&' was encountered in parsing 
    { 
     shellFunc(); //main function to prompt user for a cmd line 
    } 
    int status = 0; 
    wait(&status); 
    printf("Child exited with status of %d\n", status); 
} 

Est-ce que cela accomplit réellement la concurrence réalisée par le shell normal?

Répondre

2

Méfiez-vous de l'affectation au lieu de la comparaison.

Attention à l'impossibilité d'exécuter une commande - exit(1); après execvp().

Je pense que j'utiliser:

if (andOp == 0) 
{ 
    int status; 
    int corpse = wait(&status); 
    printf("Child %d exited with status 0x%04X\n", corpse, status); 
} 

C'est, je n'attendre si le « & » était absent. Cependant, avec les enfants d'arrière-plan qui meurent au hasard, vous devez garder une trace des processus d'arrière-plan, et en particulier, vous devez boucler wait() jusqu'à ce que l'enfant que vous venez de découper meurt. Donc, vous devez également piéger ce PID à partir du fork(). Vous voudrez peut-être vous amuser et utiliser waitpid() après avoir recueilli l'enfant que vous attendiez, pour nettoyer tous les autres corps, en utilisant l'option non bloquante de sorte que s'il n'y a pas de tels enfants, il revient immédiatement. Vous l'utiliserez toujours en boucle, de sorte que si 6 tâches de fond sont toutes terminées, vous les récupérerez toutes. Alternativement encore, vous pourriez envisager d'ignorer les signaux «mort d'enfant» (SIGCHLD) - et de laisser le système en prendre soin. Toutefois, un shell signale généralement la fin d'un des jobs d'arrière-plan.

0

Quelques problèmes:

  • si l'exec échoue?
    • Vous devez tuer l'enfant
  • si un signal se produit dans le parent?
    • L'attente se termine. Vous devez détecter et ré-attendre.
  • Appelez le ShellFunc() de manière récursive ne aide pas car il n'y a pas de véritable stratergy de sortie.
    • Utilisez int sigaction() pour détecter une erreur enfant sur des tâches en arrière-plan.