Sto utilizzando Ubuntu 9.10 (Karmic Koala) e ho dato un'occhiata alla struttura jmp_buf
che è semplicemente un array di 12 pollici. Quando utilizzo setjmp
e passo in una struttura jmp_buf
— 4 di 12 voci vengono salvate. Queste 4 voci sono il puntatore dello stack, il puntatore del frame, il contatore del programma e l'indirizzo di ritorno. A cosa servono le altre 8 voci? Sono dipendenti dalla macchina? Un'altra voce è il registro di base della tabella dei segmenti? Cos'altro è necessario per ripristinare correttamente un ambiente thread/processo? Ho esaminato la pagina man, altre fonti, ma non sono riuscito a trovare il codice assembly per setjmp
.Cosa contiene ciascuna voce nella struttura Jmp_buf?
risposta
su MacOS X 10.6.2, l'intestazione <setjmp.h>
finisce con <i386/setjmp.h>
, e lì si dice:
#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
Si potrebbe probabilmente trovare esigenze simili su Linux - il jmp_buf
contiene informazioni sufficienti per memorizzare il necessario stato. E, per usarlo, non hai davvero bisogno di sapere cosa contiene; tutto ciò che devi fare è avere fiducia che gli implementatori l'abbiano capito correttamente. Se vuoi modificare l'implementazione, allora devi capirlo, ovviamente.
Si noti che setjmp e longjmp sono molto specifici della macchina. Leggi "The Standard C Library" di Plauger per una discussione su alcuni dei problemi coinvolti nella loro implementazione. Chip più moderni rendono più difficile l'implementazione davvero buona.
setjmp
/longjmp
/sigsetjmp
dipendono in gran parte dall'architettura della CPU, dal sistema operativo e dal modello di threading. Le prime due funzioni notoriamente (o infamemente - a seconda del tuo POV) sono apparse nel kernel originale di Unix come un modo "strutturato" per uscire da una chiamata di sistema fallita, come da un errore di I/O o da altre situazioni sgradevoli.
I commenti della struttura in /usr/include/setjmp.h (Linux Fedora) dicono Chiamare l'ambiente, oltre a possibilmente una maschera di segnale salvata. Include /usr/include/bits/setjmp.h per dichiarare jmp_buf di avere una matrice di sei valori di 32 bit, apparentemente specifici della famiglia x86.
Sebbene non sia stato possibile trovare una sorgente diversa da uno PPC implementation, i commenti suggeriscono che le impostazioni della FPU devono essere salvate. Questo ha senso dal momento che non riescono a ripristinare la modalità di arrotondamento, la dimensione predefinita dell'operando, la gestione delle eccezioni, ecc. Sarebbe sorprendente.
E 'tipico di ingegneri di sistema di riservare un po' più spazio di quanto effettivamente necessario in una tale struttura. Alcuni byte in più non fanno quasi fatica a sudare, soprattutto considerando la rarità degli usi effettivi di setjmp
/longjmp
. Avere troppo poco spazio è sicuramente un pericolo. La ragione più saliente che riesco a pensare è avere qualcosa in più, piuttosto che essere puntuale: se la versione della libreria di runtime viene modificata per richiedere più spazio in jmp_buf, avendo spazio aggiuntivo già prenotato, non è necessario ricompilare i programmi che si riferiscono a esso.