c - 在收到 SIGSEGV 或 SIGBUS 后,进程能否以某种方式继续而不会崩溃?
问题描述
我正在处理一个项目,该项目处理影响相同数据的多个进程和线程。我有一行代码可能导致分段错误,因为可以从任何地方更新数据。对于那条特定的行,如果它导致分段错误,我想以某种方式处理它而不是让程序崩溃。如果前一个导致分段错误,我可以简单地更新内存位置。有没有办法做到这一点?
更新(我的案例的简短摘要):
我想要非常快速地访问文件。为此,我调用 mmap(2) 将该文件映射到所有访问它的进程中。我写入文件的数据采用特定数据结构的形式,并且会消耗大量内存。因此,如果出现我映射的大小不够的情况,我需要增加文件大小并使用新大小再次 mmap(2) 该文件。为了增加大小,我调用了 ftruncate(2)。ftruncate(2) 可能会被任何进程调用,因此它最终可能会缩小文件。所以我需要检查我正在访问的内存是否不会导致段错误。我正在使用 macOS。
解决方案
这可以工作,但是通过将信号处理程序带入图片中,您会使进程间和线程间锁定问题变得更加复杂。我想建议一种替代方法:在映射文件的第一页中保留一个字段以指示数据结构的预期大小。使用fcntl
文件锁来调解对此字段的访问。
当任何进程想要更新大小时,它会拿一个写锁,读取当前值,增加它,msync
s页面(使用MS_ASYNC|MS_INVALIDATE
应该足够了),然后使用ftruncate
放大文件,然后放大它的文件映射,并且只有然后释放写锁。如果在获取写锁之后,您发现文件已经比您想要的大小大,只需放大映射并删除锁,不要调用 ftruncate 或更改字段。
这确保了协作进程永远不会使文件变小,并且每个进程映射的内存区域始终由分配的存储支持,因此您永远不应该得到任何SIGBUS
es. 请注意,磁盘上文件的大小只会在您实际写入新分配的空间时增加,这要归功于稀疏文件的魔力。
推荐阅读
- gradle - 升级到 grails 3,现在无法解析类 org.codehaus.groovy.grails.web.servlet.mvc.GrailsParameterMap
- ansible - 当未解析定义的变量时,Ansible playbook 不会跳过任务
- sql - 在 MS Access Query 中使用多选列表框中的值
- batch-file - 为什么这条将文件从一个驱动器复制到另一个驱动器的批处理行只完成了一半?
- git - 将合并恢复为主,保留功能分支更改,而不更改历史记录
- ansible - 限制 shell 命令结果列表中的 ansible 输出
- intellij-idea - IntelliJ 运行 maven 任务并同时启动 jar?
- ansible - ansible - 类型不正确。预期的“对象”
- wpf - 在 wpf 应用程序中删除 shift+space 上的网格列
- java - Android Studio:运行我的程序时出错