2013-10-21 4 views
8

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?

Antwort

4

ich an der GNU libc Implementierung gesucht ucontext auf x86/Linux-Architekturen, so könnte es verschiedene Implementierungen sein, für die sich die folgenden nicht halten.

Die GNU libc manual besagt, dass:

Der UCP Parameter an die makecontext weitergegeben wird getContext durch einen Aufruf initialisiert werden.

Wenn Sie bei mcontext_t in glibc aussehen/sysdeps/Unix/Linux/x86/sys/ucontext.h gibt es einen Zeiger auf den Floating-Point-Zustand (fpregset_t fpregs), die in getContext initialisiert() und dereferenziert wieder in setcontext(). Es wird jedoch nicht mit makecontext() initialisiert. Ich habe einen schnellen Test mit GDB und ich bekam einen segfault in SetContext(), wenn zu dereferenzieren der Zeiger auf den Floating-Point-Kontext in einem ucontext_t versuchen Struktur nicht durch getContext initialisiert():

=> 0x00007ffff784308c < +44 >: fldenv (% RCX)

+0

Nun, das ganz das Geheimnis löst. – kibibyte