Jmp_buf 结构中的每个条目保存什么?

发布于 2024-08-13 05:08:01 字数 269 浏览 8 评论 0原文

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

I am running Ubuntu 9.10 (Karmic Koala), and I took a look at the jmp_buf structure which is simply an array of 12 ints. When I use setjmp, and pass in a jmp_buf structure—4 out of 12 entries are saved off. These 4 entries are the stack pointer, frame pointer, program counter and return address. What are the other 8 entries for? Are they machine-dependent? Is another entry the segment table base register? What else is needed to properly restore a thread/process's environment? I looked through the man page, other sources, but I couldn't find the assembly code for setjmp.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不知在何时 2024-08-20 05:08:01

在 MacOS X 10.6.2 上,标头 最终使用 ,其中显示:

#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

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

请注意,setjmp 和 longjmp 是非常特定于机器的。阅读 Plauger 的“标准 C 库”,了解其中涉及的一些问题的讨论在实施它们时。更现代的芯片使得真正更好地实施变得更加困难。

On MacOS X 10.6.2, the header <setjmp.h> ends up using <i386/setjmp.h>, and in there it says:

#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

You would probably find similar requirements on Linux - the jmp_buf contains enough information to store the necessary state. And, to use it, you really don't need to know what it contains; all you need to do is trust that the implementers got it correct. If you want to alter the implementation, then you do need to understand it, of course.

Note that setjmp and longjmp are very machine specific. Read Plauger's "The Standard C Library" for a discussion of some of the issues involved in implementing them. More modern chips make it harder to implement really well.

洋洋洒洒 2024-08-20 05:08:01

setjmp/longjmp/sigsetjmp高度依赖于CPU架构、操作系统和线程模型。前两个函数著名地(或臭名昭著地——取决于你的观点)出现在原始 Unix 内核中,作为一种“结构化”方式来摆脱失败的系统调用,例如 I/O 错误或其他令人讨厌的情况。

/usr/include/setjmp.h (Linux Fedora) 中的结构注释表示调用环境,以及可能保存的信号掩码。它包括 /usr/include/bits/setjmp.h 来将 jmp_buf 声明为有一个由 6 个 32 位整数组成的数组,显然是 x86 系列特有的。

虽然我找不到除了 PPC 实现,那里的注释合理地暗示应该保存 FPU 设置。这是有道理的,因为无法恢复舍入模式、默认操作数大小、异常处理等会令人惊讶。

系统工程师通常会在这种结构中保留比实际需要多一点的空间。一些额外的字节几乎没什么值得担心的——特别是考虑到 setjmp/longjmp 的实际使用很少。空间太小肯定是一个危险。我能想到的最重要的原因是拥有额外的空间(而不是恰到好处),如果运行时库版本更改为在 jmp_buf 中需要更多空间,则通过已保留额外的空间,无需重新编译引用的程序它。

setjmp/longjmp/sigsetjmp are highly dependent on the CPU architecture, operating system, and threading model. The first two functions famously (or infamously—depending on your POV) appeared in the original Unix kernel as a "structured" way to unwind out of a failed system call, as from an i/o error or other nasty situations.

The structure's comments in /usr/include/setjmp.h (Linux Fedora) say Calling environment, plus possibly a saved signal mask. It includes /usr/include/bits/setjmp.h to declare jmp_buf to have an array of six 32-bit ints, apparently specific to the x86 family.

While I couldn't find source other than a PPC implementation, the comments there reasonably hint that FPU settings should be saved. That makes sense since failing to restore the rounding mode, default operand size, exception handling, etc. would be surprising.

It's typical of system engineers to reserve a little more space than actually needed in such a structure. A few extra bytes are hardly anything to sweat—especially considering the rarity of actual uses of setjmp/longjmp. Having too little space definitely is a hazard. The most salient reason I can think of is having extra—as opposed to being spot on—is that if the runtime library version is changed to need more space in jmp_buf, by having extra room already reserved, there's no need to recompile programs referring to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文