我在列表中写了一些结构信息。结构是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;
}
答案 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
的函数在堆上创建内容。)
同样,您对列表的kopf
或head
所称的不是它的主要内容。它是与列表中的一个节点关联的数据。头部将是它的第一个元素。