[英]Avoid crash after doing mmap() on a file that is unmounted
我正在对可以卸载的文件执行mmap()(该文件位于用户可以随时删除的USB设备上),如果文件已卸载,我的应用程序崩溃然后我尝试访问任何元素在缓冲区。
对此有何解决方案?
首先,我想说这应该作为一个很好的论据, 不要不必要地使用 mmap
作为“优化读取”或类似的。 除了设备删除之外,其他进程的文件截断等问题都可能导致访问SIGBUS
错误。
如果确实需要使用mmap
,可以为SIGBUS
安装信号处理程序。 它的任务基本上应该是:
SIGBUS
发生,所以故障代码可以知道。 MAP_FIXED
调用mmap
以在错误页面的顶部映射新的匿名页面。 可选地填充数据,该数据将被访问地图的代码识别为错误的; 这可能使步骤1变得不必要。 另一种方法是在访问映射之前设置全局(或线程局部) jmp_buf
,并让信号处理程序简单地调用longjmp
。
请注意, mmap
和longjmp
都不是异步信号安全的,但所讨论的SIGBUS
不是异步信号(尽管如果故障访问发生在非同步信号安全库函数内,例如sscanf
它应该被认为是一个) )。 只要它是你自己的代码,而不是库函数,访问地图,你应该是安全的。 并且mmap
在大多数/所有实际实现中都是异步信号安全的,所以即使它不是正式的,你也应该在实践中使用第一个解决方案。
最简单的方法是设置一个信号处理程序,检查对与mmap
ed地址对应的内存位置的访问。
您将使用信号处理程序的sigaction
形式,而不是简单的signal
处理程序,因为sigaction
处理程序在struct __siginfo *
参数中接收与信号地址对应的信息。 可以检查它是否在mmap
ed文件的地址范围内。
当你不想处理缓冲区读/写数据的复杂性时, mmap
很棒,但是你只会因为出错而得到一种形式的错误(信号)。 使用read
/ write
机制,您可以获取errno
并确定发生了什么。 在这种情况下,它是开发人员的选择。
要在收到信号后跳转到某个位置,那么您将需要使用setjmp
和longjmp
/ siglongjmp
- 请参阅此问题中的一些用法
不要访问不可用的文件。 检查文件是否仍然存在,或使用无法卸载的文件。
您可以使用http://linux.die.net/man/7/inotify获取有关文件,目录的任何更改的通知。 你可以考虑使用IN_DELETE。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.