我正在对可以卸载的文件执行 mmap()(该文件位于用户可以随时删除的 USB 设备上),如果文件被卸载,我的应用程序崩溃,然后我尝试访问任何元素在缓冲区中。
有什么解决办法吗?
首先,我想说这应该作为一个很好的论据,不要 mmap
不必要地用作“优化读取”或类似的东西。除了设备删除之外,其他进程截断文件等问题也可能导致访问错误SIGBUS
。
如果确实需要使用mmap
,可以为SIGBUS
. 它的任务基本上应该是:
SIGBUS
,以便可以知道错误代码。mmap
withMAP_FIXED
以在错误页面之上映射一个新的匿名页面。可以选择用访问地图的代码将其识别为错误的数据填充它;这可能使步骤 1 变得不必要。另一种方法是jmp_buf
在访问地图之前设置一个全局(或线程本地),并让信号处理程序简单地调用longjmp
.
请注意,异步信号mmap
也不longjmp
是安全的,但有SIGBUS
问题的不是异步信号(尽管如果错误访问发生在非异步信号安全的库函数中,则可能应该将其视为异步信号sscanf
)。只要它是您自己的代码,而不是库函数,访问地图,您应该是安全的。并且mmap
在大多数/所有现实世界的实现中都是异步信号安全的,因此即使在形式上不正确,您也应该对实践中的第一个解决方案感到满意。
最简单的事情是设置一个信号处理程序,该处理程序将检查对与mmap
ed 地址对应的内存位置的访问。
您将使用sigaction
信号处理程序的形式,而不是更简单的signal
处理程序,因为处理程序在与信号地址对应sigaction
的参数中接收信息。struct __siginfo *
可以检查这个是否在mmap
ed文件的地址范围内。
mmap
当您不想处理缓冲区读取/写入数据的复杂性时,这很好,但由于出现问题,您只会得到一种形式的错误(信号)。使用read
/write
机制,您可以获得errno
并确定发生了什么。在这种情况下,这在很大程度上是开发人员的选择。
要在接收到信号后跳转到某个位置,那么您需要使用setjmp
and longjmp
/ siglongjmp
- 请参阅this question中的一些使用
不要访问不可用的文件。检查文件是否还在,或者使用无法卸载的文件。
您可以使用http://linux.die.net/man/7/inotify获得有关文件、目录的任何更改的通知。您可以考虑使用 IN_DELETE。