从c中的列表中读取函数中的结构

时间:2014-06-13 09:37:39

标签: c list struct

我在列表中写了一些结构信息。结构是Pstatus,全局定义为pGlobal。现在我想在函数getStatus()中使用pGlobal从这个列表中读取,但这不起作用。所以我创建了另一个定义pGlobal2但是这会产生很多问题。我想读出我的清单,但我得到一些虚假的信息。在这个列表中存储正在运行的进程的pids,但是当我读出它时,我只得到最后一个pid和信息,但是我得到它与存储pid一样多。如果此列表中存储了5个pid,我将获得最后一个5次。我认为那是因为我有pGlobal和pGlobal2。有人能帮助我吗?

    #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();
    Pstatus pGlobal;
    Pstatus *pGlobal2;

    Liste procTable;


    int aufruf(Kommando k, int forkexec){

        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 */  
              pGlobal = 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, &pGlobal);
              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("pointer1: %p",test);
              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);
                    if (WEXITSTATUS(kind_status) == 0) {
                        /** setze status exit(0) */ 
                        printf("Kind erfolgreich\n");
                        pGlobal = statusAendern(pGlobal,pid,"exit(0)"); 
                    } 
                    /* nicht erfolgreiche ausgeführt */
                    else 
                    {
                        /** setze status exit(1) */ 
                        printf("Kind nicht erfolgreich\n");
                        pGlobal = statusAendern(pGlobal,pid,"exit(1)"); 
                    }
                }
                else if(WIFSIGNALED(kind_status)){
                    printf("Kind mit der PID %d wurde durch Signal abgebrochen. Signalnummer: %d\n",pid, WTERMSIG(kind_status));
                    pGlobal = statusAendern(pGlobal,pid,"signal"); 
                }
          }
          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;

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

          /* NYI */
        getStatus();

      }

      return aufruf(k, forkexec);
    }

    int getStatus() {

        Liste temp, temp2;

        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){

            pGlobal2 = listeKopf(temp);

            /*printf("check: %d\n",pGlobal2->check);*/

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

            if(strcmp(pGlobal2->status, "RUNNING") != 0) {
                pGlobal2->check = 1;
            }   

            /*if(strcmp(pGlobal2->status, "RUNNING") == 0) {
                printf("eintrag behalten");
                listeAnfuegen(temp2, pGlobal2);
            }*/


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

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

}

我有结构

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;

听着:

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

listeKopf:

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

listeAnfuegen:

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

1 个答案:

答案 0 :(得分:0)

你提供了大量的信息,但不是关键的东西。所以我假设erzeugeProzess返回结构Pstatus。您可以将节点添加到列表中,如下所示:

pGlobal = erzeugeProzess(pid, k->u.einfach.worte[0], "RUNNING");
procTable = listeAnfuegen(procTable, &pGlobal);

因此,您始终将pGlobal的地址添加到列表中,当然,该地址始终包含上次调用erzeugeProzess时指定的内容。 (这也是你的代码无法使用局部变量的原因:列表中的引用位于堆栈的某个位置,很可能不包含有用的信息。)

解决方案是让erzeugeProzess真正在堆栈上创建一个对象,例如:

Pstatus *proc_new(...)
{
    Pstatus *proc = malloc(sizeof(*proc));

    // initialise
    return proc;
}

这将在堆上创建一个具有自己数据的新进程,您可以将其分配给列表。不过,您需要free处理过程。

完成此操作后,您将不再需要全局变量。使用局部变量。您不会丢失引用,因为您将它存储在列表中:

Pstatus *p = proc_new(pid, k->u.einfach.worte[0], "RUNNING");
procTable = listeAnfuegen(procTable, p);

作为旁注:您的代码有一些非常尴尬的命名约定。例如erzeugeProzess表示createProces,但在您的版本中,它不会创建任何内容。 (通常假设create或其名称包含new的函数在堆上创建内容。)

同样,您对列表的kopfhead所称的不是它的主要内容。它是与列表中的一个节点关联的数据。头部将是它的第一个元素。