Jmp_buf结构中的每个条目都有什么作用?

Set*_*zer 12 c callstack longjmp

我正在运行Ubuntu 9.10(Karmic Koala),我看了一下jmp_buf结构,它只是一个12个整数的数组.当我使用setjmp并传入jmp_buf结构时,12个条目中的4个被保存.这4个条目是堆栈指针,帧指针,程序计数器和返回地址.其他8个条目是什么?它们是机器相关的吗?段表基址寄存器的另一个条目是?还有什么需要正确恢复线程/进程的环境?我查看了手册页,其他来源,但我找不到汇编代码setjmp.

Jon*_*ler 10

在MacOS X 10.6.2上,标题<setjmp.h>最终使用<i386/setjmp.h>,并在其中说:

#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
Run Code Online (Sandbox Code Playgroud)

您可能会在Linux上找到类似的要求 - jmp_buf包含足够的信息来存储必要的状态.而且,要使用它,你真的不需要知道它包含什么; 你需要做的就是相信实施者得到了正确的答案.如果你想改变实现,那么你当然需要理解它.

请注意,setjmp和longjmp是非常特定于机器的.阅读Plauger的" 标准C库 ",讨论实现它们所涉及的一些问题.更现代的芯片使得实施起来更加困难.


wal*_*lyk 6

setjmp/ longjmp/ sigsetjmp高度依赖于CPU架构,操作系统和线程模型.前两个函数着名(或臭名昭着 - 取决于你的POV)出现在原始的Unix内核中作为一种"结构化"的方式来解除失败的系统调用,如来自i/o错误或其他令人讨厌的情况.

结构在/usr/include/setjmp.h(Linux Fedora)中的注释表示调用环境,可能还有保存的信号掩码. 它包括/usr/include/bits/setjmp.h,用于声明jmp_buf具有六个32位整数的数组,显然特定于x86系列.

虽然我找不到PPC实现以外的其他来源,但那里的评论合理地暗示应该保存FPU设置.这是有道理的,因为无法恢复舍入模式,默认操作数大小,异常处理等将是令人惊讶的.

系统工程师通常会保留比这种结构中实际需要的空间更多的空间.一些额外的字节几乎没什么可汗的 - 特别是考虑到setjmp/ 的实际使用的罕见性longjmp.空间太小肯定是危险的.我能想到的最显着的原因是,如果将运行时库版本更改为需要更多空间在jmp_buf中,通过额外的空间已经保留,则无需重新编译引用的程序.它.