2012-10-15 33 views
5

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

对此的任何解决方案?

回答

-1

请勿访问不可用的文件。检查文件是否仍然存在,或使用无法卸载的文件。

+4

由于可能的竞赛条件,我不认为这是非常有用的。围绕访问映射区域的代码期望并捕获“SIGBUS”会有帮助吗?或者类似的东西? –

+1

编号'SIGBUS'不一定是可恢复的,尽管一些实现在从处理程序返回后重试错误指令。 –

+0

@SimonRichter你不需要重试错误指令,你只需要确定你不能继续读/写,之后你停止尝试访问区域并返回给调用者一些错误指示。也许'setjmp()'/'longjmp()'可以避免重新执行错误指令。 –

2

最简单的事情就是设置一个信号处理程序,用于检查对应于mmap编址的存储器位置的访问。

你会使用sigaction形式的信号处理程序,而不是简单的signal处理器为sigaction处理对应于信号的地址struct __siginfo *参数接收信息。可以检查它是否位于mmap ed文件的地址范围内。

mmap当你不想处理缓冲区读/写数据的复杂性,但是由于出错而只能得到一种形式的错误(信号)时,它非常棒。通过read/write机制,您可以获得errno并确定发生了什么。在这种情况下,它非常适合开发者。

要跳转到一个位置接收到信号后,那么你就需要利用setjmplongjmp/siglongjmp的 - 看到this question

6

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

如果确实需要使用mmap,则可以安装SIGBUS的信号处理程序。它的任务应该主要是为了:

  1. 设置一个SIGBUS发生了全球性(或线程本地,如果你的程序是多线程)标志,所以出错的代码可以做到心中有数。
  2. 拨打mmapMAP_FIXED可以在错误页面顶部映射一个新的匿名页面。可选填写访问地图的代码将被识别为错误的数据;这可能会导致第1步不必要。

另一种方法是设置一个全球性的(或者线程本地)访问地图前jmp_buf,并且已经在信号处理程序只需调用longjmp

注意,无论是mmap也不longjmp是异步信号安全的,但有问题的SIGBUS不是异步信号(尽管它应该算得上一个,如果断裂访问发生在非异步信号安全库内功能如sscanf)。只要它是你自己的代码,而不是库函数,访问地图,你就应该安全。并且mmap在大多数/所有现实世界的实现中都是异步信号安全的,因此即使它在形式上不正确,您也应该在实践中使用第一种解决方案。

+2

会这样说:对于'mmap'来说更多的不是满足眼睛 - 因为错误处理比传统的I/O要复杂得多。这不一定是一个理由_against using_'mmap' ...只是意识到你召唤的精神;-) –

+0

并确保他们不会飞出你的鼻子.. :-) –

-1

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

+3

这些通知将是立即因为OP试图遏制的页面错误?如果没有,请不要打扰。 –

+0

看来你必须调用'read()'来查明是否有任何改变,但是在'read()'没有返回任何兴趣和下面的内存访问之间可能发生改变。这是一个竞赛条件。此外,事件队列可能会溢出。所以,这不是一个解决方案。 –