2010-08-08 7 views
1

Je lis GNU/Linux demande la programmation de la 2e édition, vous pouvez atteindre ce que je lis de here .Après J'écris le code similaire à la sienne, mais il fonctionne étrangement:simple shell en utilisant execlp va étrangement

$ ./shell 
./shell>>quit 
$ ./shell 
./shell>>date 
Sun Aug 8 21:19:37 CST 2010 
./shell>>quit 
$ ./shell 
./shell>>abc 
execlp failed: No such file or directory 
./shell>>quit 
./shell>>quit 
$./shell 
./shell>>abcd execlp 
execlp failed: No such file or directory 
./shell>>quit 
./shell>>quit 

les premier et deuxième cas sont ok, mais les troisième et quatrième les deux ont besoin un peu quit à quit.This est pas ce que je suis expecting.I deviner quelque chose ne va pas avec fork(), ou waitpid(), mais cela reste non résolu après demander à quelques personnes autour de moi.Maintenant, c'est l'heure d'été, c'est-à-dire les vacances d'été, je n'ai plus de compagnons à y aller.Merci toujours.

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

#define LINE_LEN 80 

int main(int argc,char* argv[]) 
{ 

pid_t pid; 
char cmd[LINE_LEN+1]={'\0'}; 

while(1) 
{ 
    printf("%s>>",argv[0]); 
    if(fgets(cmd,sizeof(cmd),stdin)==NULL) 
    { 
    perror("fgets failed"); 
    break; 
    } 
    cmd[strlen(cmd)-1]='\0'; 
    if(strncmp(cmd,"quit",4)==0) 
    { 
    break; 
    } 
    if((pid=fork())==-1) 
    { 
    perror("fork failed"); 
    break; 
    }else if(pid==0) 
    { 
    //TODO no option can be specified for cmd 
    execlp(cmd,cmd,NULL); 
    perror("execlp failed"); 
    }else 
    { 
    waitpid(pid,NULL,0); 
    } 
} 
return 0; 
} 

Répondre

3

Normalement, si execlp réussit, votre processus d'enfant devient le nouveau processus, et donc l'exécution de votre code arrête efficacement à ce moment-là.

Maintenant, le execlp a échoué, vous imprimez l'erreur, et continuer le processus enfant comme si rien ne s'est passé! Vous devez exit(0) l'enfant, si le execlp a échoué.

+0

Thanks.I voir ce que vous voulez dire.Le code dans le livre ne fait aucune vérification d'erreur sur execlp, donc cette correction peut aller à l'errata? – schemacs

+0

définitivement! Si votre livre ne le dit pas, rappelez-vous ceci: * vérifiez toujours les valeurs de retour * – mvds

+0

(bien que, pour la classe de fonctions 'exec', le fait que votre code soit encore en vie est une indication d'échec, vérifiant ainsi une valeur de retour est strictement pas nécessaire de savoir que les choses se sont mal passées ...) – mvds

0

execlp échoue si cmd n'existe pas. Comme le dit à juste titre mvds, lorsque execlp échoue, vous devez quitter le processus enfant. Mais je recommande de ne pas forcer quand cmd n'existe pas.

Vous pouvez utiliser quelque chose comme access (voir access(2)) avant d'utiliser fork pour vous assurer que cmd existe (dans votre PATH), et est un exécutable.

+0

Oui, je devrais appeler l'accès avant de passer cmd à execlp.Merci beaucoup. – schemacs

+0

UPDATE: l'accès (avec X_OK) vérifie seulement le nom du chemin, pas le nom du fichier (c'est-à-dire que je dois le trouver avec le chemin.) – schemacs

0

Juste après la version de débogage pour préciser: strncmp est appelé dans ce procédé, et lorsque l'enfant ou à la sortie des parents

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

#define LINE_LEN 80 

int main(int argc,char* argv[]) 
{ 

    pid_t pid; 
    char cmd[LINE_LEN+1]={'\0'}; 

    while(1) 
    { 
     printf("%s>>",argv[0]); 
     if(fgets(cmd,sizeof(cmd),stdin)==NULL) 
     { 
      perror("fgets failed"); 
      break; 
     } 
     cmd[strlen(cmd)-1]='\0'; 
     if(strncmp(cmd,"quit",4)==0) 
     { 
      printf("process :%d in strncmp equal\n",getpid()); 
      break; 
     } 
     if((pid=fork())==-1) 
     { 
      perror("fork failed"); 
      break; 
     }else if(pid==0) 
     { 
      printf("new child:%d\n",getpid()); 
      //TODO no option can be specified for cmd 
      execlp(cmd,cmd,NULL); 
      perror("execlp failed"); 
      //This is critical 
      //exit(0); 
     }else 
     { 
      printf("parent:%d(his child is %d)\n",getpid(),pid); 
      waitpid(pid,NULL,0); 
     } 
    } 
    printf("process :%d exit...\n",getpid()); 
    return 0; 
} 

Il suffit de voir un cas:

./shell 
./shell>>abc 
parent:8356(his child is 8357) 
new child:8357 
execlp failed: No such file or directory 
./shell>>quit 
process :8357 in strncmp equal 
process :8357 exit... 
./shell>>quit 
process :8356 in strncmp equal 
process :8356 exit... 
Questions connexes