2014-06-12 5 views
0

몇 가지 기본 기능이있는 셸을 작성했습니다. 모든 실행 된 프로세스가 나열된 프로세스 목록을 가져야한다. 필자는이 정보를 Pstatus라는 구조체에 씁니다. Pstatus는 전역 목록에 기록됩니다. getStatus()에서이 목록을 읽으려고하면 정보가 작동하지 않습니다. 나는 정보가 아닌 기호를 얻는다. 필자가이 글로벌 목록에 정보를 쓰는 기능에서 똑같은 과정을 정확하게 수행한다면 올바른 정보를 얻을 수 있습니다. 내 목록에 뭐가 잘못 됐는지 모르겠다.코드의 의미 오류

http://pastebin.com/XGVZcSB4

정보는 테이블 (proctable)에 aufruf() 라인 (203)에 기록된다.

의 getStatus() 라인 내가 구조체

typedef struct { 
int pid;  /* Prozess ID */ 
char* name;  /* Prozess Name (Programm) */ 
char* status; /* Status des Programms */ 
int check;  /* bereits abgerufen? 1 - abgerufen, 0 - nicht abgerufen */ 
} Pstatus; 

들어있어 정보

갖고 싶어 311

:

typedef struct liste { 
    void *kopf; 
    struct liste *rest; 
} *Liste; 

listeKopf을 :

void* listeKopf(Liste l) { 
    if(l==NULL) 
    abbruch("listeKopf(listeLeer) undefiniert"); 
    return l->kopf; 
} 

목록보기 :

Liste listeAnfuegen(Liste l, void* element){ 
    Liste neu=reserviere(sizeof (struct liste)); 
    neu->kopf = element; 
    neu->rest = l; 
    return neu; 
} 

나를 도울 수있는 사람은 누구입니까?

편집! 코드 :

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


      #include "utils.h" 
      #include "listen.h" 
      #include "wortspeicher.h" 
      #include "kommandos.h" 
      #include "frontend.h" 
      #include "parser.h" 
      #include "variablen.h" 

      int interpretiere(Kommando k, int forkexec); 
      int interpretiere_einfach(Kommando k, int forkexec); 
      int getStatus(); 

      Liste procTable; 

      void do_execvp(int argc, char **args){ 
       execvp(*args, args); 
       perror("exec-Fehler"); 
       fprintf(stderr, "bei Aufruf von \"%s\"\n", *args); 
       exit(1); 
      } 

      int interpretiere_pipeline(Kommando k){ 
       /* NOT IMPLEMENTED */ 

       int fd1[] = { -1, -1 }; 
       int fd2[] = { -1, -1 }; 
       int i = 0; 
       int status = 0; 
       int pid = -2; 
       Liste l = k->u.sequenz.liste; 
       Kommando ko; 
       Pstatus pDesk; 
       int laenge = k->u.sequenz.laenge; 

       printf("Länge: %i!\n", laenge); 

       for (i = 0; i < laenge; i++) { 
        ko = (Kommando) listeKopf(l); 
        fd2[0] = fd1[0]; 
        fd2[1] = fd1[1]; 

        if (i > 0) { 
         close(fd2[1]); 
        } 

        if (pipe(fd1) < 0) { 
         perror("Pipe-Fehler"); 
         exit(1); 
        } 
        pid = fork(); 

        switch (pid) { 
        case -1: 
         perror("Fehler bei fork"); 
         return (-1); 
        case 0: 
         /*1. Prozess? Dann den Lesestrom von FD2 nicht umlegen.:*/ 
         if (fd2[0] != -1) { 
          dup2(fd2[0], STDIN_FILENO); 
         } 

         /*Letzter Prozess? Dann den Schreibstrom von FD1 nicht umlegen:*/ 
         if (i < laenge - 1) { 
          dup2(fd1[1], STDOUT_FILENO); 
         } 
         interpretiere_einfach(ko, 0); 
         exit(1); 
         break; 
        default: 
         /*pDesk = erzeugeProzess (pid, k->u.einfach.worte[0], "RUNNING"); 
         procTable = listeAnfuegen(procTable, &pDesk); */ 
         pDesk = erzeugeProzess(pid, "test", "RUNNING"); 
         procTable = listeAnfuegen(procTable, &pDesk); 

         sleep(1); 
         break; 
        } 
        l = listeRest(l); 
       } 
       return status; 
      } 

      int umlenkungen(Kommando k){ 
       Umlenkung *u;  /* Objekt vom Typ Umlenkung (kommandos.h) */ 
       Modus modus;  /* Objekt vom Typ Modus (kommandos.h) */ 
       Liste neueListe; /* Objekt vom Typ Liste (listen.h) */ 
       FILE *f;   /* File zum erstellen einer eventuellen Datei */  
       /*int fd;   Filedescriptor zum Überprüfen der Datei*/ 
       char *pfad;   /* Pfad und Dateiname der Datei */ 

       /** 
       typedef  struct { 
        int   filedeskriptor; beliebige Deskriptoren können umgelenkt werden 
        Modus  modus;   Umlenkungsart 
        char *  pfad;   Datei von der/in die umgelenkt wird 
       } Umlenkung; 
       * */ 
       /* 
       * Wenn Umlenkungen vorhanden sind, hole die Umleitungen aus der Liste 
       * und wandle sie um in ein struct Umleitungen 
       **/ 
       if(k->u.einfach.umlenkungen != NULL){ 
        fprintf(stdout, "Es sind Umleitungen vorhanden\n"); 
        neueListe = k->u.einfach.umlenkungen; 

        u = (Umlenkung *) neueListe->kopf; 
        modus = u->modus; /* Modi: read, write, append*/ 
        pfad = u->pfad;  /* Pfad zur Datei*/ 


        /* Modi definiert in kommandos.h */ 
        switch(modus) { 
        case READ: /* stellt die Standarteingabe auf die angegeben Datei 'pfad'*/ 
         fprintf(stdout, "Modus Read\n"); 
         if(freopen(pfad, "r", stdin) == NULL){ 
          fprintf(stderr, "Fehler beim Lesen der Datei. \nErrno: %d \n", errno); 
          return 1; 
         } 
         break; 

        case WRITE: /* Standartausgabe wird auf die Datei Pfad gestellt. Existiert die Datei noch nicht, wird sie erstellt. */ 
         fprintf(stdout, "Modus Write\n"); 
         /*fd = open(pfad, O_RDWR | O_CREAT | O_TRUNC, S_IWGRP | S_IRGRP | S_IXGRP); 
          if(fd == -1) { 
           fprintf(stdout, "Fehler beim Erstellen der Datei.\n Errno: %d", errno); 
          exit(1); 
         }*/ 
         if ((f = fopen(pfad, "w+")) == NULL) { 
          fprintf(stderr, "Fehler beim Erstellen der Datei. \nErrno: %d \n", errno); 
          return 1; 
         } 
         if(freopen(pfad, "w", stdout) == NULL){ 
          fprintf(stderr, "Fehler beim Erstellen der Datei. \nErrno: %d \n", errno); 
          return 1; 
         } 
         break; 

        case APPEND: 
         fprintf(stdout, "Modus Append\n"); 
         /*fd = open(pfad, O_RDWR | O_CREAT | O_APPEND, S_IWGRP | S_IRGRP | S_IXGRP | S_IWUSR | S_IRUSR | S_IXUSR | S_IWOTH | S_IROTH | S_IXOTH); 
          if(fd == -1) { 
           fprintf(stdout, "Fehler beim Erstellen der Datei"); 
          exit(1); 
         }*/ 
         if ((f = fopen(pfad, "a+")) == NULL) { 
          fprintf(stderr, "Fehler beim Erstellen der Datei. \nErrno: %d \n", errno); 
          return 1; 
         } 
         if(freopen(pfad, "a", stdout) == NULL){ 
          fprintf(stderr, "Fehler beim Erstellen der Datei. \nErrno: %d \n", errno); 
          return 1; 
         } 
         break; 

        default: 
         fprintf(stderr, "Modus default.\n No Options defined for default.\n"); 
         fprintf(stdout, "Modus default nicht verfuegbar.\n"); 
         break; 
        } 

       } 
       return 0; 
      } 

      int aufruf(Kommando k, int forkexec){ 

       Pstatus p; 
       Pstatus *test; 
       int kind_status, i; 

       /* Programmaufruf im aktuellen Prozess (forkexec==0) 
       oder Subprozess (forkexec==1) 
       */ 

       if(forkexec){ 
       int pid=fork(); 

       switch (pid){ 
       case -1: 
        perror("Fehler bei fork"); 
        return(-1); 
       case 0: 
        if(umlenkungen(k)) 
       exit(1); 
        do_execvp(k->u.einfach.wortanzahl, k->u.einfach.worte); 
        abbruch("interner Fehler 001"); /* sollte nie ausgeführt werden */ 
       default: 
        if(k->endeabwarten) { 
         /* So einfach geht das hier nicht! */ 

         /* schreibt die PID, den Namen und den Status in die Tabelle */ 
         p = erzeugeProzess (pid, k->u.einfach.worte[0], "RUNNING"); /*k->u.einfach.worte[0] */ 
         /* Debug: print 
         printf("\npid: %d\tstatus: %s\n", p.pid, p.status); 
         */ 
         i = listeLaenge(procTable); 
         procTable = listeAnfuegen(procTable, &p); 
         if(listeLaenge(procTable) <= i) { 
         fprintf(stderr, "Fehler beim Schreiben in die Liste!"); 
         } 

         /* Debug printf: Bis hierhin wird alles ordentlich in die Liste geschrieben! 
         test = listeKopf(procTable); 
         printf("\npid: %d\tstatus: %s\n", test->pid, test->status); 
         */ 

         waitpid(pid, &kind_status, 0); 
         if(WIFEXITED(kind_status)){ 
          printf("Kind mit der PID %d wurde beendet\n",pid); 
         } 
         else if(WIFSIGNALED(kind_status)){ 
          printf("Kind mit der PID %d wurde durch Signal abgebrochen. Signalnummer: %d\n",pid, WTERMSIG(kind_status)); 
         } 
        } 
        else { 
        fprintf(stderr, "Programm nicht beendet\n"); 
        fprintf(stdout, "PID: %i\n", pid); 
        } 
        return 0; 
       } 
       } 

       /* nur exec, kein fork */ 
       if(umlenkungen(k)) 
       exit(1); 
       do_execvp(k->u.einfach.wortanzahl, k->u.einfach.worte); 
       abbruch("interner Fehler 001"); /* sollte nie ausgeführt werden */ 
       exit(1); 
      } 


      int interpretiere_einfach(Kommando k, int forkexec){  

       char **worte = k->u.einfach.worte; 
       int anzahl=k->u.einfach.wortanzahl; 

       if (strcmp(worte[0], "exit")==0) { 
       switch(anzahl){ 
       case 1: 
        exit(0); 
       case 2: 
        exit(atoi(worte[1])); 
        printf("Dies ist ein test"); 
       default: 
        fputs("Aufruf: exit [ ZAHL ]\n", stderr); 
        return -1; 
       } 
       } 

       if (strcmp(worte[0], "cd")==0) { 
       switch(anzahl){ 
       case 1: 
        return chdir(getenv("HOME")); 
       case 2: 
        return chdir(worte[1]); 
       default: 
        fputs("Aufruf: cd [ PFAD ]\n", stderr); 
        return -1; 
       } 
       } 

       /* gibt den Status der Subprozesse zurück */ 
       if (strcmp(worte[0], "status")==0){ 

        /* NYI */ 
       getStatus(); 

       } 

       return aufruf(k, forkexec); 
      } 

      int getStatus() { 

       Pstatus *p; 
       Liste temp; 

       fprintf(stdout, "---------------------\n----Statustabelle----\n---------------------\n"); 

       temp = procTable; 

       printf("laenge der liste: %d\n",listeLaenge(temp)); 


       /*fprintf(stdout, "Pid: %d", p->pid);*/ 



       if(listeLaenge(temp) < 1) { 
        fprintf(stdout, "Liste ist leer.\n"); 
        return 0; 
       } 


       while(temp != NULL){ 

        /*fprintf(stdout, "%s", listeKopf(temp)); */ 
        p = listeKopf(temp); 

        /*if(p->check < 1) {*/ 
        fprintf(stdout,"PID: %d, Programm: %s, Status: %s\n",p->pid, p->name, p->status); 
        /*} */ 

        /* wenn status != running -> p.checked() */ 

        temp = listeRest(temp); 
        } 
       return 0; 
      } 

      int interpretiere(Kommando k, int forkexec){ 
       int status; 

       switch(k->typ){ 
       case K_LEER: 
       return 0; 
       case K_EINFACH: 
       return interpretiere_einfach(k, forkexec); 
       case K_SEQUENZ: 
       { 
        Liste l = k->u.sequenz.liste; 
        while(!listeIstleer(l)){ 
        status=interpretiere ((Kommando)listeKopf(l), forkexec); 
        l=listeRest(l); 
        } 
       } 
       return status; 
       /* 
       * Status wird auf 0 gesetzt. While Schleife arbeitet Befehle 
       * ab solange der return Wert (status) 0 ist. 
       * Erreicht der status den Wert ungleich 0, wird die Funktion mit 
       * return 1 abgebrochen. 
       **/ 
       case K_UND: 
       { 
        Liste l = k->u.sequenz.liste; 
        status = 0; 
        while(!listeIstleer(l) && status == 0){ 
        status=interpretiere ((Kommando)listeKopf(l), forkexec); 
        l=listeRest(l); 
        if(status != 0) { 
         return 1; 
        } 
        } 
        /*printf("UND noch nicht implementiert");*/ 
       } 
       return 0; 
       /* 
       * Status wird auf 1 gesetzt. While Schleife arbeitet Befehle 
       * ab solange der return Wert (status) nicht 0 ist. 
       * Erreicht der status den Wert 0, wird die Funktion mit return 1 
       * abgebrochen. 
       **/ 
       case K_ODER: 
       { 
        Liste l = k->u.sequenz.liste; 
        status = 1; 
        while(!listeIstleer(l) && status != 0){ 
        status=interpretiere ((Kommando)listeKopf(l), forkexec); 
        l=listeRest(l); 
        if(status == 0) { 
         return 1; 
        } 
        } 
        /*printf("ODER noch nicht implementiert");*/ 
       } 
       return 0; 
       /* 
       * UND Befehl. Noch nicht implementiert! 
       * return Wert überarbeiten! 
       **/ 
       case K_PIPE: 
       { 
        /*printf("Pipeline noch nicht implementiert");*/ 
        return interpretiere_pipeline(k); 
       } 
       return 0; 
       default: 
       fputs("unbekannter Kommandotyp, Bearbeitung nicht implementiert\n", stderr); 
       break; 
       } 
       return 0; 
      } 
+0

우편 번호 여기

-Caius. – yizzlez

답변

0

당신이 당신의 글로벌 procTable 목록에 로컬 변수를 추가하는 것 같다. 이것은 83 행의 interpretiere_pipeline 함수에서 발생합니다. pDesk은 로컬 변수이며 C 컴파일러는이를 스택에 저장합니다. 현재 함수가 반환 될 때, 그 메모리 프레임은 할당 해제되고 다음에 호출되는 것에 의해 점유됩니다.

문제점의 해결책은 힙에 pDesk을 할당하는 것입니다. 이렇게하면 목록에 항상 유효한 주소를 저장하고 주소를 지정합니다. 이 도움이

희망,

+0

대단히 감사합니다. 그 해결책이 도움이되었습니다. 베니 – user1550036