5

我正在对可以卸载的文件执行 mmap()(该文件位于用户可以随时删除的 USB 设备上),如果文件被卸载,我的应用程序崩溃,然后我尝试访问任何元素在缓冲区中。

有什么解决办法吗?

4

4 回答 4

8

首先,我想说这应该作为一个很好的论据,不要 mmap不必要地用作“优化读取”或类似的东西。除了设备删除之外,其他进程截断文件等问题也可能导致访问错误SIGBUS

如果确实需要使用mmap,可以为SIGBUS. 它的任务基本上应该是:

  1. 设置一个发生的全局(或线程局部,如果您的程序是多线程的)标志SIGBUS,以便可以知道错误代码。
  2. 调用mmapwithMAP_FIXED以在错误页面之上映射一个新的匿名页面。可以选择用访问地图的代码将其识别为错误的数据填充它;这可能使步骤 1 变得不必要。

另一种方法是jmp_buf在访问地图之前设置一个全局(或线程本地),并让信号处理程序简单地调用longjmp.

请注意,异步信号mmap也不longjmp是安全的,但有SIGBUS问题的不是异步信号(尽管如果错误访问发生在非异步信号安全的库函数中,则可能应该将其视为异步信号sscanf)。只要它是您自己的代码,而不是库函数,访问地图,您应该是安全的。并且mmap在大多数/所有现实世界的实现中都是异步信号安全的,因此即使在形式上不正确,您也应该对实践中的第一个解决方案感到满意。

于 2012-10-15T13:21:56.990 回答
3

最简单的事情是设置一个信号处理程序,该处理程序将检查对与mmaped 地址对应的内存位置的访问。

您将使用sigaction信号处理程序的形式,而不是更简单的signal处理程序,因为处理程序在与信号地址对应sigaction的参数中接收信息。struct __siginfo *可以检查这个是否在mmaped文件的地址范围内。

mmap当您不想处理缓冲区读取/写入数据的复杂性时,这很好,但由于出现问题,您只会得到一种形式的错误(信号)。使用read/write机制,您可以获得errno并确定发生了什么。在这种情况下,这在很大程度上是开发人员的选择。

要在接收到信号后跳转到某个位置,那么您需要使用setjmpand longjmp/ siglongjmp- 请参阅this question中的一些使用

于 2012-10-15T10:56:36.777 回答
-2

不要访问不可用的文件。检查文件是否还在,或者使用无法卸载的文件。

于 2012-10-15T10:25:22.980 回答
-2

您可以使用http://linux.die.net/man/7/inotify获得有关文件、目录的任何更改的通知。您可以考虑使用 IN_DELETE。

于 2012-10-15T13:34:40.127 回答