2014-02-11 28 views
0

它是c中的一些linux shell的實現。由於我已經添加了後臺進程支持,我有一些輸出,我不明白。下面是代碼:爲什麼我的流程表現得像這樣?

#include <stdlib.h> 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/time.h> 
#include <sys/resource.h> 
#include <signal.h> 
#include <wait.h> 

#define DEFAULT_PROMPT "\nLog710H2014%>" 
#define EXIT_CMD "exit" 
#define CD_CMD "cd" 
#define HOME_ENV_VAR "HOME" 
#define NEW_LINE "\n**************************************************\n" 
#define BCG_CMD_FLAG "&" 

void cd_handler(int argc, char *argv[]); 
int lire(char *chaine, int longueur); 
char** init_command(int* size,char *str); 
int execProg(int *argc, char **argv); 
int execProgBg(int *argc, char **argv); 
void sigchldHandler(int sig_num); 

struct beanProcess { 
    pid_t pid; 
    int job_num; 
    char *command; 
}; 

struct beanProcess *beans; 

int jobCount = 1; 

int main() { 

    printf(NEW_LINE); 
    printf("Bienvenue sur le shell de l'equipe 1"); 
    printf(NEW_LINE); 

    while(1){ 
     char str[200]; 
     printf(DEFAULT_PROMPT); 

     lire(str, 200); 
     int commArgsC = 0, bg = 0; 
     char** comms = init_command(&commArgsC, str); 

     if(commArgsC == 0){ 
      printf("Saisie vide, veuillez entrez une commande."); 
      continue; 
     } 

     if(strcmp(comms[commArgsC-1], BCG_CMD_FLAG) == 0){ 
      bg = 1; 
      comms[commArgsC-1] = 0; 
     } 
     if(strcmp(comms[0], CD_CMD) == 0){ 
      cd_handler(commArgsC, comms); 
      commArgsC = commArgsC -1; 
     } 
     else if (strcmp(comms[0], EXIT_CMD) == 0){ 
      exit(0); 
     } 
     else { 
      if(bg){ 
       execProgBg(&commArgsC, comms); 
      } 
      else{ 
       execProg(&commArgsC, comms); 
      } 
     } 
    } 
    exit; 
} 
void cd_handler(int argc, char *argv[]){ 
    char buff[512]; 
    char * directory; 

    if(argc < 2){ 
     directory = getenv(HOME_ENV_VAR); 
    }else if (argc == 2){ 
     directory = argv[1]; 
    }else{ 
     exit(1); 
    } 

    if (chdir(directory) == -1) { 
     printf ("Erreur de changement de repertoire actif", strerror (errno)); 
    }else{ 
     if (getcwd(buff, sizeof(buff)) == NULL) 
      perror("Impossible d'afficher le repertoire courant"); 
     else 
      printf("le repertoire courant est: %s\n", buff); 
    } 
} 
//Cette fonction est adaptée a partir du code de refp sur http://stackoverflow.com/questions/11198604/c-split-string-into-an-array-of-strings 
char** init_command(int* size, char* str){ 
    char ** res = NULL; 
    char * p = strtok (str, " "); 
    int n_spaces = 0; 

    while (p) { 
     res = realloc (res, sizeof (char*) * ++n_spaces); 

     if (res == NULL){ 
      exit (-1); 
     } 
     res[n_spaces-1] = p; 
     p = strtok (NULL, " "); 
    } 
    res = realloc (res, sizeof (char*) * (n_spaces+1)); 
    res[n_spaces] = 0; 
    *size = n_spaces; 
    return res; 
} 
//cette fonction est tirée d'un exemple de http://fr.openclassrooms.com/informatique/cours/apprenez-a-programmer-en-c/recuperer-une-chaine-de-caracteres 
int lire(char *chaine, int longueur) 
{ 
    char *positionEntree = NULL; 

    if (fgets(chaine, longueur, stdin) != NULL) 
    { 
     positionEntree = strchr(chaine, '\n'); 
     if (positionEntree != NULL) 
     { 
      *positionEntree = '\0'; 
     } 
     return 1; 
    } 
    else 
    { 
     return 0; 
    } 
} 
int execProg(int *argc, char **argv){ 
    char path[] = "/bin/"; 
    strcat(path,argv[0]); 
    printf("\nThis is the %d process executing the code in non bg mode\n", getpid()); 
    printf("Voici le resultat de l'execution de votre commande\n"); 
    pid_t pid; 
    pid = fork(); 

    if (pid < 0) { 
     perror("Creation de processus avec fork echouee"); 
     exit(-1); 
    } 
    else if (pid == 0) { 
     if(execvp(argv[0], argv) == -1){ 
      printf("\nthis is the child process %d executing the command in non bg mode\n", getpid()); 
      perror("execv"); 
      return EXIT_FAILURE; 
     } 
    } 
    else { 
     printf("\nthis is the parent process %d showing the stats in non bg mode\n", getpid()); 
     struct rusage rusg; 
     long temp, tempCpu; 
     wait (NULL); 
     getrusage(RUSAGE_CHILDREN, &rusg); 
     printf("\nStatistique de la commande %s:\n", argv[0]); 

     temp = (rusg.ru_utime.tv_sec * 1000) + (rusg.ru_utime.tv_usec/1000); 
     tempCpu = (rusg.ru_stime.tv_sec * 1000) + (rusg.ru_stime.tv_usec/1000); 

     printf("\nLe temps wall-clock (ms): %ld", temp); 
     printf("\nLe temps CPU (ms) %ld", tempCpu); 
     printf("\nNB interruptions volontaires: %ld", rusg.ru_nvcsw); 
     printf("\nNB interruptions involontaires: %ld", rusg.ru_nivcsw); 
     printf("\nNB defaults de pages: %ld", rusg.ru_majflt); 
     printf("\nNB defaults de pages satifaits du noyau : %ld", rusg.ru_minflt); 
    } 
    return EXIT_SUCCESS; 
} 
int execProgBg(int *argc, char **argv){ 

    signal(SIGCHLD, sigchldHandler); 
    printf("\nThis is the %d process executing the code in bg mode\n", getpid()); 

    pid_t pid; 
    pid = fork(); 

    if (pid < 0) { 
     perror("Creation de processus avec fork echouee"); 
     return EXIT_FAILURE; 
    } 
    else if (pid == 0) { 
     //printf("This is the pid %d", getpid()); 
     printf("\nthis is the child process %d executing the command in bg mode\n", getpid()); 

     if(execvp(argv[0], argv) == -1){ 
      perror("execvp"); 
      return EXIT_FAILURE; 
     } 
    } 
    else { 
     printf("\nthis is the parent process %d showing the queue in bg mode\n", getpid()); 

     printf("[%d] %d", jobCount, pid); 
     jobCount++; 
     //cleanJobList(childPid); 

     //ajoutProcess(); 
    } 
    return EXIT_SUCCESS; 
} 
void sigchldHandler(int sig_num) 
{ 
    int status; 
    int childPid; 
    childPid = waitpid(-1, &status, 1); 
    printf("Hello the process %d has died\n", childPid); 
    //cleanJobList(childPid); 
} 

當我執行如「ls &」一個bg命令,這裏的輸出:

************************************************** 
Bienvenue sur le shell de l'equipe 1 
************************************************** 

Log710H2014%>ls & 

This is the 23464 process executing the code in bg mode 

this is the parent process 23464 showing the queue in bg mode 
[1] 23472 
Log710H2014%> 
this is the child process 23472 executing the command in bg mode 
Debug PARTIE3.c 
Hello the process 23472 has died 

This is the 23464 process executing the code in non bg mode 
Voici le resultat de l'execution de votre commande 

this is the parent process 23464 showing the stats in non bg mode 
Debug PARTIE3.c 

Statistique de la commande ls: 

Le temps wall-clock (ms): 0 
Le temps CPU (ms) 2 
NB interruptions volontaires: 2 
NB interruptions involontaires: 9 
NB defaults de pages: 0 
NB defaults de pages satifaits du noyau : 644 
Log710H2014%> 

這是爲什麼父進程重疊里拉()函數和直接進入execProg函數在第一次執行後?

+0

'Debug PARTIE3.c'從哪裏來? – Nabla

+0

命令ls& – user2966439

回答

1

您在while循環中。當你的函數返回時,無論它返回什麼,循環都會繼續。如果你想停止,你需要break或致電exitexecProgBg

這是爲什麼父進程重疊里拉()函數和 直接進入execProg函數的第一個執行後

我不知道你是如何執行你的程序,但它看起來像第二次fgets失敗,您不會注意到,因爲您不檢查lire函數的返回碼。所以你繼續並重新使用之前調用的緩衝區。看起來你可能會通過EOF這個程序 - 也許是按ctrl-d。


我決定運行代碼並獲得與OP確實通過敲擊第一ls &後CTRL-d相同的結果。


這是除了點,但值得一些解釋:

exit; 

該評估函數退出其轉換爲一個函數指針和扔掉的結果。 它不會調用函數。更重要的是,由於main正在退出,所以將退出命令作爲main的最後一個語句是毫無意義的。你應該只是return some_code表示失敗的成功。

+0

我已經糾正了退出問題,但仍然爲什麼我的prog在循環的第二次迭代中不阻塞lire函數(其中包含來自stdin的fgets)? – user2966439

+0

@Nabla這個問題在此期間進行了編輯,第一次我沒有看到第二部分。看着。 – cnicutar

+0

@Nabla'fgets'失敗。它看起來像EOF,但可能是一些微妙的東西。 – cnicutar

相關問題