Linux - signal处理的一些补充

signal是一类比较特殊的存在,需要kernel和userspace通力合作才能将signal处理流程走通。

Android 平台 Native 代码的崩溃捕获机制及实现对signal的描述比较完整,建议读读。


signal处理流程

简单的流程描述如下:

userspace:

  • 利用系统调用sigaction(…)或signal(…)设置感兴趣的signal的属性,包括处理函数、flags等。
  • 已经不鼓励使用signal系统调用,在libc中被封装成sigaction的调用。

kernel:

  • 在处理sigaction时,把userspace的signal处理函数地址以及flags保存在当前进程的控制块中:

    task_struct->sighand->action[]
    
  • 当有signal触发后,会将相应signal number在如下成员中置位,并置目标进程的状态为TIF_SIGPENDING,然后唤醒目标进程;如果目标进程处于running状态且运行于其他CPU,则发送reschedule IPI中断以便目标进程可以进入kernel并在退出kernel时处理signal;如果目标进程就是当前进程,则在退出kernel时处理signal;如果目标进程从睡眠状态被唤醒,检测到有signal pending,也会退出睡眠状态,从而返回user space。

    task_struct->pending
    task_struct->signal->shared_pending
    
  • 在进程被唤醒并返回userspace前夕, 发现TIF_SIGPENDING置位,从而执行信号处理函数do_signal(…)。

  • do_signal: 根据signal number,从 task_struct->sighand->action[]中得到sigaction后,在进程的user stack或user专门的处理信号stack上建立 struct rt_sigframe栈帧。当前kernel stack中的数据会复制到struct rt_sigframe的成员uc.uc_mcontext中。以signal的user处理函数为返回地址,然后返回用户空间。

    • SA_RESTORER:为了保证执行完user signal handler后能够立刻返回kernel,返回地址指向一个特殊的user函数__restore_rt,实现在libc中。这个地址是在sigaction时传递给kernel的。__restore_rt如下(以x86_64为例)。可见就是系统调用rt_sigreturn,直接进入kernel。

       ENTRY_PRIVATE(__restore_rt)
      .L__restore_rt_START:
        mov $__NR_rt_sigreturn, %rax
        syscall
      .L__restore_rt_END:
      END(__restore_rt)
      

userpsace:

  • 进入userspace时,直接进入signal handler函数。执行完毕后,函数返回。根据上面所述,返回的地址就是__restore_rt,从而进入kernel。

kernel:

  • 进入stub_rt_sigreturn -> sys_rt_sigreturn,恢复信号处理之前的现场,包括恢复uc.uc_mcontext中的数据至kernel stack中、signal handler stack等,以便下次返回userspace时可进入正常流程。

以上就是signal处理的简化流程。


栈的问题

这里再说明一下处理signal时所用的栈的问题。可以用进程的用户栈或用专用于处理signal的栈,在Android上使用的是后者。

在Bionic的文件pthread_create.cpp中,有如下的函数实现:

pthread_create
   -> __pthread_start
      ->__init_alternate_signal_stack

在线程的入口函数__pthread_start中,会分配一段user空间作为信号处理栈空间,并利用系统调用sigaltstack将此栈的地址和长度告诉kernel,kernel会将此地址和长度保存在如下地方:

  task_struct -> sas_ss_sp
  task_struct -> sas_ss_size

后期在处理此线程的signal时,将此栈作为signal处理函数的栈。


signal的作用域

signal的作用域是进程,跨进程是无效的。在实现signal时,充分利用此限制,从而简单化了处理流程。

从上述的流程分析可见,kernel会保存user signal handler的地址,待处理signal时直接跳转至此地址。由于各个进程的userspace是不一样的,此进程的handler地址在其他进程内是无效或不是期望的函数地址。

那么作用域是线程还是进程的线程组昵?如果signal是给线程的,则pending在 task_struct->pending上;如果是给线程组的,则pending在 task_struct->signal->shared_pending。 由fork时的copy_signal(…)可见,当创建线程时所有的线程共享同一个对象task_struct->signal。

可参见kill, tgkill。kill是发送signal给进程,而tgkill则是发送signal给线程。

what(): OGRE EXCEPTION(9:UnimplementedException): in GL3PlusTextureGpu::copyTo at /build/ogre-next-UFfg83/ogre-next-2.2.5+dfsg3/RenderSystems/GL3Plus/src/OgreGL3PlusTextureGpu.cpp (line 677) [ruby $(which ign) gazebo-1] Stack trace (most recent call last) in thread 29813: [ruby $(which ign) gazebo-1] #10 Object "[0xffffffffffffffff]", at 0xffffffffffffffff, in [ruby $(which ign) gazebo-1] #9 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7ff5c16ae84f, in [ruby $(which ign) gazebo-1] #8 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7ff5c161cac2, in [ruby $(which ign) gazebo-1] #7 Object "/lib/x86_64-linux-gnu/libQt5Core.so.5", at 0x7ff5bbd4499d, in [ruby $(which ign) gazebo-1] #6 Object "/lib/x86_64-linux-gnu/libQt5Core.so.5", at 0x7ff5bbd42f90, in qTerminate() [ruby $(which ign) gazebo-1] #5 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7ff5bdbc5276, in std::terminate() [ruby $(which ign) gazebo-1] #4 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7ff5bdbc520b, in [ruby $(which ign) gazebo-1] #3 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7ff5bdbb9b9d, in [ruby $(which ign) gazebo-1] #2 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7ff5c15b07f2, in abort [ruby $(which ign) gazebo-1] #1 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7ff5c15ca475, in raise [ruby $(which ign) gazebo-1] #0 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7ff5c161e9fc, in pthread_kill [ruby $(which ign) gazebo-1] Aborted (Signal sent by tkill() 29649 1000) 这些是什么意思
03-14
<think>好的,我现在需要解决用户关于OGRE UnimplementedException异常的问题。用户遇到了“OGRE EXCEPTION(9:UnimplementedException) GL3PlusTextureGpu::copyTo”这个错误,特别是在使用OgreNext和Gazebo时,想了解原因和解决方法。 首先,我得回忆一下OGRE引擎的相关知识。OGRE是一个开源的图形渲染引擎,常用于游戏和仿真软件中,比如Gazebo。UnimplementedException通常意味着代码中某个功能尚未实现或被调用了一个未支持的方法。错误信息中提到的是GL3PlusTextureGpu::copyTo,这可能涉及到纹理处理的部分,尤其是在使用OpenGL 3+的后端渲染系统时。 接下来,我需要查阅相关文档和社区讨论。用户提供的引用中提到了Gazebo的不同版本,比如Indigo默认用Gazebo2,升级到Gazebo3需要特定步骤,以及Harmonic版本的安装问题。但直接关于OgreNext和这个异常的引用可能没有,所以可能需要结合一般性的OGRE问题来解决。 可能的第一个原因是OgreNext版本与Gazebo或其他依赖库的版本不兼容。OgreNext是OGRE引擎的下一代分支,可能对某些功能进行了重构或删减。如果用户使用的Gazebo版本依赖的是旧版的OGRE,而他们却安装了OgreNext,可能会导致部分接口不匹配,从而触发未实现异常。 另一个可能的原因是图形驱动问题。OpenGL的某些功能可能不被用户的显卡驱动支持,尤其是在使用较新的OpenGL版本时。例如,GL3Plus渲染系统可能需要特定的扩展或驱动版本,而用户的当前驱动可能不符合要求。 此外,代码中的纹理复制操作可能在OgreNext中未被正确实现,或者在调用时传入了不支持的参数,比如纹理格式或尺寸不符合要求。例如,尝试复制一个压缩纹理或非2的幂次方纹理时,如果底层实现未处理这种情况,就会抛出异常。 解决方法方面,首先应检查OgreNext和Gazebo的版本兼容性。确保Gazebo支持的OGRE版本与安装的OgreNext版本一致。可能需要降级OgreNext或升级Gazebo到适配的版本。其次,更新图形驱动到最新版本,确保支持所需的OpenGL特性。此外,检查纹理的格式和参数,确保符合OgreNext的要求,必要时修改纹理设置或转换格式。如果问题依旧,可以查阅OgreNext的官方文档或社区论坛,寻找类似问题的解决方案,或提交问题报告。 用户提供的引用中提到Gazebo安装时可能涉及ROS版本和依赖库的问题,比如引用[2]提到Indigo搭配Gazebo2,升级Gazebo3需要特定步骤。这可能暗示系统库或依赖项的不匹配也可能导致此类异常,需要检查相关依赖是否正确安装。 总结下来,解决步骤可能包括:验证版本兼容性、更新驱动、检查纹理参数、查阅社区资源。需要一步步排除可能的原因,从软件配置到硬件支持逐一排查。</think>### OGRE UnimplementedException异常原因及解决方法 #### 1. **异常原因分析** **OGRE EXCEPTION(9:UnimplementedException)** 通常表示在调用 `GL3PlusTextureGpu::copyTo` 方法时,OgreNext 的渲染后端未实现该功能。可能原因包括: - **版本兼容性问题**:OgreNext 与 Gazebo 或相关插件(如 ArduPilot Gazebo 插件)的版本不兼容,导致部分接口未对齐[^3]。 - **OpenGL 驱动支持不足**:显卡驱动未完全支持 OpenGL 3+ 特性,或 OgreNext 的 `GL3Plus` 渲染系统对某些纹理操作(如纹理复制)的支持存在限制[^1]。 - **纹理参数不合法**:尝试复制不支持的纹理格式(如压缩纹理)或非标准尺寸纹理(如非 2 的幂次方纹理)。 #### 2. **解决方法** **步骤 1:检查版本兼容性** - 确认使用的 **OgreNext 版本** 是否与 Gazebo 要求的 OGRE 版本匹配。例如,Gazebo Garden 可能依赖特定 OGRE 分支[^2]。 - 若使用 ROS2 Iron 或 Gazebo Harmonic,需确保依赖库(如 `ros-indigo-desktop-full`)已正确安装。 **步骤 2:更新图形驱动** - 升级显卡驱动至最新版本,确保支持 OpenGL 3.3+: ```bash sudo apt-get update && sudo apt-get upgrade mesa-utils libgl1-mesa-dri ``` **步骤 3:验证纹理参数** - 检查代码中纹理的 **格式** 和 **尺寸**,确保符合 OgreNext 的要求。例如: ```cpp // 示例:创建 2 的幂次方纹理(如 512x512) TexturePtr texture = TextureManager::getSingleton().createManual( "MyTexture", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, 512, 512, 0, PF_R8G8B8A8 ); ``` **步骤 4:回退或升级软件版本** - 若问题与 OgreNext 的已知 Bug 相关,尝试回退到稳定版本(如 Ogre 1.12)或升级到修复版本[^1]。 - 对于 Gazebo,参考官方文档调整依赖版本(如从 Gazebo3 升级到 Gazebo Garden)。 **步骤 5:查阅社区资源** - 在 OgreNext 的 GitHub Issues 或 Gazebo 论坛中搜索类似问题,例如: > "GL3PlusTextureGpu::copyTo not implemented in OgreNext with Gazebo" #### 3. **补充说明** 若问题仍未解决,可尝试在 **非GL3Plus渲染系统** 下运行(如切换到 DirectX 或 Vulkan 后端),或提交详细的错误日志至 OgreNext 开发者社区。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值