LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 647|回复: 2

问一个非本地跳转的问题

[复制链接]
发表于 2005-10-23 21:50:37 | 显示全部楼层 |阅读模式
在调用longjmp返回到setjmp的位置的时候。进程的文件描述符,信号屏蔽字这些会不会改变啊?
发表于 2005-10-24 09:31:47 | 显示全部楼层
我想不会,跳转而已,又没跨进程
回复 支持 反对

使用道具 举报

发表于 2005-10-24 15:45:41 | 显示全部楼层
非本地跳转通常是通过修改堆栈指针和程序计数器来实现的,所以不会改变你说的这些内容。

例如,下面是 GLibc 中的部分代码,它实现了 setjmp。

  1. ENTRY (BP_SYM (setjmp))
  2.         /* Note that we have to use a non-exported symbol in the next
  3.            jump since otherwise gas will emit it as a jump through the
  4.            PLT which is what we cannot use here.  */
  5.         ENTER

  6.         movl JMPBUF(%esp), %eax
  7.         CHECK_BOUNDS_BOTH_WIDE (%eax, JMPBUF(%esp), $JB_SIZE)

  8.              /* Save registers.  */
  9.         movl %ebx, (JB_BX*4)(%eax)
  10.         movl %esi, (JB_SI*4)(%eax)
  11.         movl %edi, (JB_DI*4)(%eax)
  12.         leal JMPBUF(%esp), %ecx        /* Save SP as it will be after we return.  */
  13.              movl %ecx, (JB_SP*4)(%eax)
  14.         movl PCOFF(%esp), %ecx        /* Save PC we are returning to now.  */
  15.              movl %ecx, (JB_PC*4)(%eax)
  16.         LEAVE /* pop frame pointer to prepare for tail-call.  */
  17.         movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */

  18.         /* Call __sigjmp_save.  */
  19.         pushl $1
  20.         pushl 8(%esp)
  21.         call BP_SYM (__sigjmp_save)
  22.         popl %ecx
  23.         popl %edx
  24.         ret
  25. END (BP_SYM (setjmp))
复制代码


再看看对应的 longjmp 的代码:

  1. ENTRY (BP_SYM (__longjmp))
  2.         ENTER

  3.         movl JBUF(%esp), %ecx        /* User's jmp_buf in %ecx.  */
  4.         CHECK_BOUNDS_BOTH_WIDE (%ecx, JBUF(%esp), $JB_SIZE)

  5.         movl VAL(%esp), %eax        /* Second argument is return value.  */
  6.         /* Save the return address now.  */
  7.         movl (JB_PC*4)(%ecx), %edx
  8.              /* Restore registers.  */
  9.         movl (JB_BX*4)(%ecx), %ebx
  10.         movl (JB_SI*4)(%ecx), %esi
  11.         movl (JB_DI*4)(%ecx), %edi
  12.         movl (JB_BP*4)(%ecx), %ebp
  13.         movl (JB_SP*4)(%ecx), %esp
  14.         /* Jump to saved PC.  */
  15.              jmp *%edx
  16. END (BP_SYM (__longjmp))
复制代码


这就是非本地跳转的原理,其实 fork 和 C++ 中的 try... throw... catch... 也利用了这个。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表