Programmieraufgabe Februar 02

ein paar Fragen…

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Programmieraufgabe Februar 02
Hab noch ein paar Lücken, vielleicht mag mir da wer helfen.

-Das zu messende Programm soll das Signal ignorieren…

Leitet ein Vaterprozess ein SIGINT automatisch an seine Kinder weiter, oder brauch ich da einfach garnichts machen? Wird ein Signalhandler beim exec() übernommen?

-Rechenzeiterfassung:

einfacher times() aufruf nach dem wait() und tms_cutime abfragen?

-Wenn der Prozess läuft soll der Sighandler “Programm xxx läuft noch” ausgeben.

Muss ich den Programmname über eine globale Variable übergeben, oder geht das eleganter irgedwie?

Achja, und zum Makefile noch (wurde zwar schon oft durchgekaut, aber definitiv verstanden hab ichs noch nicht). Müssen wir wissen welche Flags wir brauchen? Oder dürfen wir einfach $(CC) $(CFLAGS) -o peter peter.c schreiben? Und was heisst “eventuell erzeugte Objectfiles”? Wenn wir nur eine .c Datei haben und nix linken, woher soll da eine eventuell erzeugtes Objectfile herkommen?


CFLAGS brauchst du in der klausur gar nicht ins makefile schreiben. evtl erzeugt objects heisst, wenn du beim bauen deines binarys den zwischenschritt über object dateien machst musst (gcc -c) musst du die im clean entfernen, wenn du gcc direkt zum kompilieren und linken benutzt und kein object erzeugt wird musst du auch keins löschen sondern nur das binary


Und der Rest meiner bescheidenen Fragen :rolleyes:


Nein der leitet nichts weiter aber du musst trotzdem sicherstellen dass das Kind (ich hab die Aufgabenstellung nicht da aber ich nehme an das zu messende Programm ist ein Kindprozess) das SIGINT ignoriert. Das heisst Du musst NACH dem fork und VOR dem exec ein sigaction für SIGINT machen und SIG_IGN setzen.

wie in der trsh gehabt vor dem wait und nach dem wait und die differenz der c(u|s)time ist dann die Zeit des aufgelesenen Kindes. Welche der Zeiten / beide / oder die Summe sollte aus der Aufgabenstellung hervorgehen.

Wie gesagt ich habe die Aufgabenstellung nicht da und nehme jetzt an dass der Vaterprozess bei einem Signal oder was auch immer diese Meldung ausgeben soll. Dann sollte der Vater doch in der Regel wissen was er für ein Kind ausgeführt hat.


Danke erstmal für die Antworten, eine Frage bleibt noch halb offen:

Aber im Signalhandler komm ich doch nicht an die Variablen aus der main() ran, oder?


ne das geht dann etwa so

char *prog;

int main(int argc, char **argv) {
 ...
  prog=argv[1];
  sigaction(SIGINT....);
....

}

Okay, also nix mit Übergabe. Und danke nochmal für deine geduldigen Antworten :smiley:


Wo kommt das Signal denn her? Wenn das SIGINT durch einen Benutzer durch ein CTRL-c ausgelöst wurde, dann wird das an alle Prozesse ausgestellt, die in diesem Terminal laufen, nicht nur an den ersten (den Vater). Ohne Aufgabenstellung können wir nur raten was gemeint ist.


Ne andere Frage zu signalbehandlung besser gesagt zu den Flags:

Wann muss ich SA_RESTART, wann SA_NOCHLDSTP,…
Oder kann man sagen bei Sig_handler:SA_RESTART und bei CHLD_handler :SA_RESTARTund SA_NOCLDSTP ?
Weiß zwar ungefähr was die Begriffe bedeuten aber nicht wie ich sie wo einsetze!? :wand: :wand: :wand: :wand: :wand:


Die Aufgabenstellung erfährst du in der Klausur vom Februar 02 (siehe Threadtitel :smiley: )
Es geht um ein time-Programm, welches (in einem Kindprozess) ein anderes Programm aufruft und dessen Rechenzeit stoppt. Bei Sigint soll Papi eine Meldung ausgeben, dass das Programm läuft und Sohnemann darfs ignorieren.
Ich war mir aber nicht sicher, ob ein Signalhandler vor exec() in das auszuführende Programm übernommen wird. Und wenn ich das richtig verstanden hab, dann ist das wohl so.


Wenn du die „Struct sigaction Peter“ ausfüllst hat die ein int „sa_flags“. Als Flag kannst du entweder SA_RESTART oder SA_NOCLDSTP (oder noch mehr => Skript) setzen. Bei SA_RESTART musst du dir um Systemaufrufe keine Sorgen machen, falls sie unterbrochen werden (mit errno=eintr). Sie werden einfach neu gestartet.
Bei SA_NOCLDSTOP bekommst du nur ein SIGCHLD wenn der Kindprozess wirklich tot ist, nicht wenn er nur eine Pause macht.

Das steht so aber auch alles in der Übungsfolie G.3 Signale (wobei man mal erwähnen sollte, dass die Übungsfolien ziemlich hilfreich sind…)


Im Prinzip ist es völlig egal woher das Signal kommt, wichtig ist nur dass es vom Sohn ignoriert wird und dafür muss man mit sigaction das Signal eben vor dem exec ignorieren.


Mal ne kleine Frage: Wenn ich ein Signal vor dem fork() blockiere oder ignoriere oder ihm ein Signalhandler zuweise, ist dann das Signal auch im Childprozess blockiert,ignoriert oder hat den vorher zugewiesenen Handler?


ja, schließlich ist das eine kopie des alten prozesses


nein, ein signalhandler ist ja eine Funktion - die gibt’s nach dem exec doch gar nicht mehr.
Deshalb wird’s auf SIG_DEFAULT zurueckgesetzt.
Signalbehandlung SIG_IGN bleibt allerdings ueber exec hinweg erhalten.

Ueber fork wird dagegen alles vererbt - da bleibt das Prozessimage ja identisch
und damit auch die handler-Funktionen erhalten.

signale ignorieren
in der aufgabenstellung heißt es man müsse alle anderen Signale im Kindprozess ignorieren. Heißt dass, das mit sie mit sigprocmask blockieren soll oder im sie in die sigaction::sa_mask reinschreiben soll?


Das heisst ja eigentlich nur, dass die Rechenzeiterfassung korrekt sein muss und nicht durch den aufruf des Signalhandlers verändert werden darf.

Deswegen verwendet man nicht den Rückgabewert von times sondern die usertime des Prozesses. Ist das der richtige Weg? Ich hab das deswegen so gemacht:

(Vaterprozess)
Signalhandler installiert [„Programm läuft noch!“]
times(&timesvorher);
wait();
times(&timesnacher);
time=timenachher.cutime - timesvorher.cutime


ich waere ueberhaupt nicht auf die idee gekommen, den rueckgabewert zu verwenden.
das wuerde doch dann im prinzip einer einfach stoppuhr entsprechen und nicht der zeit, die die cpu mit dem prozess verbraucht hat, oder?


Da das Programm sich eh nur einmal forkt und dann terminiert, kannst du auch einfach die cutime (Children-User-Time) verwenden. Wenn nur ein Kind gelaufen ist, müsste die Zahl da drin eigentlich stimmen.