Ich nahm Betriebssysteme im letzten Jahr, in dem ich Benutzerkontexte verwendet (im Header ucontext.h
definiert) einen Thread-Scheduler zu implementieren für ein Projekt (in dem jeder Thread einen Prozess simuliert). Ich nehme in einem Vorlesungsteil und wird über Benutzerkontexten, und es nur fiel mir reden, dass trotz dieses Projekt im vergangenen Jahr getan zu haben, ich verstehe nicht wirklich, was genau das getcontext
Systemaufruf tatsächlich der Fall ist.Was macht der getcontext-Systemaufruf (ucontext.h) wirklich?
Die man-Seiten für getcontext
besagt, dass es "die Struktur initialisiert, auf die von ucp auf den gerade aktiven Kontext verwiesen wird." Darin heißt es auch, für das Argument zu setcontext
, dass „wenn das UCP Argument mit getContext() erstellt wurde, die Programmausführung fortgesetzt, als ob der entsprechende Aufruf von getContext() hatte gerade zurückgekehrt.“ Okay, ich verstehe das.
Also hier ist, was ich bin verwirrt. Typischerweise für die Art, wie ich es gelernt, einen Kontextwechsel durchzuführen, würde man die ucontext_t
Struktur und Swap/set es als solches initialisieren:
ucontext_t ucp;
ucontext_t oucp;
getcontext(&ucp);
// Initialize the stack_t struct in the ucontext_t struct
ucp.uc_stack.ss_sp = malloc(STACK_SIZE);
ucp.uc_stack.ss_size = STACK_SIZE;
ucp.uc_stack.ss_flags = 0;
ucp.uc_link = /* some other context, or just NULL */;
// Don't block any signals in this context
sigemptyset(&ucp.uc_sigmask);
// Assume that fn is a function that takes 0 arguments and returns void
makecontext(&ucp, fn, 0);
// Perform the context switch. Function 'fn' will be active now
swapcontext(&oucp, &ucp);
// alternatively: setcontext(&ucp);
Wenn ich getcontext
in kleineren Programmen weglassen, nichts Interessantes passiert. In etwas größeren Programmen, in denen es mehr Kontextwechsel über Benutzerkontexte gibt, erhalte ich einen Segmentierungsfehler, der nur gelöst wird, indem man getcontext
zurückfügt.
Was genau tut getcontext
? Warum kann ich nicht einfach eine ucontext_t
Struktur zuweisen, initialisieren, indem ich die Felder uc_stack
und uc_sigmask
initialisiere, und makecontext
ohne die getcontext
aufrufen? Gibt es eine notwendige Initialisierung, die getcontext
führt, dass makecontext
nicht funktioniert?
Nun, das ganz das Geheimnis löst. – kibibyte