2009-12-01 11 views
9

Ich benutze Ubuntu 9.10 (Karmic Koala), und ich schaute mir die jmp_buf Struktur an, die einfach ein Array von 12 Ints ist. Wenn ich setjmp benutze und eine jmp_buf Struktur — übertrage, werden 4 von 12 Einträgen gespeichert. Diese 4 Einträge sind der Stapelzeiger, der Rahmenzeiger, der Programmzähler und die Rücksprungadresse. Wofür sind die anderen 8 Einträge? Sind sie maschinenabhängig? Ist ein anderer Eintrag das Segmenttabellenbasisregister? Was ist noch erforderlich, um die Umgebung eines Threads/Prozesses ordnungsgemäß wiederherzustellen? Ich schaute durch die Manpage, andere Quellen, aber ich konnte den Assemblercode für setjmp nicht finden.Was hat jeder Eintrag in der Jmp_buf-Struktur?

Antwort

8

auf MacOS X 10.6.2, der Header <setjmp.h> landet <i386/setjmp.h> verwenden, und es sagt dort:

#if defined(__x86_64__) 
/* 
* _JBLEN is number of ints required to save the following: 
* rflags, rip, rbp, rsp, rbx, r12, r13, r14, r15... these are 8 bytes each 
* mxcsr, fp control word, sigmask... these are 4 bytes each 
* add 16 ints for future expansion needs... 
*/ 
#define _JBLEN ((9 * 2) + 3 + 16) 
typedef int jmp_buf[_JBLEN]; 
typedef int sigjmp_buf[_JBLEN + 1]; 

#else 

/* 
* _JBLEN is number of ints required to save the following: 
* eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags, eip, 
* cs, de, es, fs, gs == 16 ints 
* onstack, mask = 2 ints 
*/ 

#define _JBLEN (18) 
typedef int jmp_buf[_JBLEN]; 
typedef int sigjmp_buf[_JBLEN + 1]; 

#endif 

Sie wahrscheinlich ähnliche Anforderungen auf Linux finden würde - die jmp_buf enthält genügend Informationen, um die notwendigen zu speichern Zustand. Und um es zu benutzen, müssen Sie wirklich nicht wissen, was es enthält; Alles, was Sie tun müssen, ist zu vertrauen, dass die Implementierer es richtig gemacht haben. Wenn Sie die Implementierung ändern möchten, müssen Sie dies natürlich verstehen.

Beachten Sie, dass setjmp und longjmp sehr maschinenspezifisch sind. Lesen Sie Plaugers "" für eine Diskussion über einige der Probleme, die bei der Implementierung dieser Probleme auftreten. Modernere Chips machen es schwieriger, wirklich gut zu implementieren.

4

setjmp/longjmp/sigsetjmp sind stark von der CPU-Architektur, dem Betriebssystem und dem Threading-Modell abhängig. Die ersten beiden Funktionen (oder infamous - abhängig von Ihrem POV) erschien im ursprünglichen Unix-Kernel als eine "strukturierte" Möglichkeit, sich aus einem fehlgeschlagenen Systemaufruf wie aus einem I/O-Fehler oder anderen unangenehmen Situationen zu lösen.

Die Kommentare der Struktur in /usr/include/setjmp.h (Linux Fedora) sagen Aufrufumgebung, plus möglicherweise eine gespeicherte Signalmaske. Es enthält /usr/include/bits/setjmp.h, um jmp_buf für ein Array von sechs 32-Bit-Ints zu deklarieren, die offensichtlich spezifisch für die x86-Familie sind.

Während ich andere Quelle als PPC implementation nicht finden konnte, weisen die Kommentare darauf hin, dass FPU-Einstellungen gespeichert werden sollten. Dies ist sinnvoll, da es nicht überraschend wäre, den Rundungsmodus, die Standardoperandengröße, die Ausnahmebehandlung usw. nicht wiederherzustellen.

Es ist typisch für Systemingenieure, etwas mehr Platz zu reservieren, als tatsächlich in einer solchen Struktur benötigt wird. Ein paar zusätzliche Bytes sind kaum etwas zum Schwitzen - besonders in Anbetracht der Seltenheit der tatsächlichen Verwendung von setjmp/longjmp. Zu wenig Platz ist definitiv eine Gefahr. Der hervorstechendste Grund, den ich mir vorstellen kann, besteht darin, dass die Version der Laufzeitbibliothek geändert werden muss, um mehr Platz in jmp_buf zu benötigen, da zusätzlicher Raum bereits reserviert ist. Es besteht keine Notwendigkeit, Programme erneut zu kompilieren es.