2009-12-01 14 views
9

Estoy ejecutando Ubuntu 9.10 (Karmic Koala), y eché un vistazo a la estructura jmp_buf que es simplemente una matriz de 12 ints. Cuando uso setjmp, y paso en una estructura jmp_buf — 4 de 12 entradas se guardan. Estas 4 entradas son el puntero de la pila, el puntero del marco, el contador del programa y la dirección de retorno. ¿Para qué son las otras 8 entradas? ¿Son dependientes de la máquina? ¿Otra entrada es la base de la tabla de segmentos? ¿Qué más se necesita para restaurar adecuadamente el entorno de un subproceso/proceso? Miré a través de la página de manual, otras fuentes, pero no pude encontrar el código de ensamblaje para setjmp.¿Qué significa cada entrada en la estructura Jmp_buf?

Respuesta

8

en MacOS X 10.6.2, la cabecera <setjmp.h> termina usando <i386/setjmp.h>, y allí se 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 

Es probable encontrar requisitos similares en Linux - la jmp_buf contiene suficiente información para almacenar la necesaria estado. Y, para usarlo, realmente no necesita saber qué contiene; todo lo que necesita hacer es confiar en que los implementadores lo corrigieron. Si desea modificar la implementación, entonces necesita comprenderla, por supuesto.

Tenga en cuenta que setjmp y longjmp son muy específicos de la máquina. Lea "The Standard C Library" de Plauger para una discusión sobre algunos de los problemas involucrados en su implementación. Los chips más modernos hacen que sea más difícil de implementar realmente bien.

4

setjmp/longjmp/sigsetjmp dependen en gran medida de la arquitectura de la CPU, el sistema operativo y el modelo de subprocesamiento. Las dos primeras funciones famosas (o infamemente, según su POV) aparecieron en el kernel original de Unix como una forma "estructurada" de salir de una llamada al sistema fallida, como un error de E/S u otras situaciones desagradables.

Los comentarios de la estructura en /usr/include/setjmp.h (Linux Fedora) dicen Entorno de llamada, más posiblemente una máscara de señal guardada. Incluye /usr/include/bits/setjmp.h para declarar que jmp_buf tiene una matriz de seis entradas de 32 bits, aparentemente específicas de la familia x86.

Aunque no pude encontrar otra fuente que no sea PPC implementation, los comentarios allí indican razonablemente que la configuración de FPU debe guardarse. Eso tiene sentido, ya que no restaurar el modo de redondeo, el tamaño de operando predeterminado, el manejo de excepciones, etc. sería sorprendente.

Es típico de los ingenieros del sistema reservar un poco más de espacio de lo que realmente se necesita en una estructura de este tipo. Unos pocos bytes adicionales no son nada para sudar, especialmente teniendo en cuenta la rareza de los usos reales de setjmp/longjmp. Tener muy poco espacio definitivamente es un peligro. La razón más sobresaliente que puedo pensar es tener algo extra, en lugar de ser perfecto, es que si la versión de la biblioteca de tiempo de ejecución se cambia para necesitar más espacio en jmp_buf, al tener espacio adicional ya reservado, no hay necesidad de recompilar programas que se refieran a eso.

Cuestiones relacionadas