在卸载的文件上执行mmap()后避免崩溃

时间:2012-10-15 10:16:54

标签: c unix kernel mmap

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

对此有何解决方案?

4 个答案:

答案 0 :(得分:7)

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

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

  1. 设置一个全局(或线程本地,如果你的程序是多线程的)标志SIGBUS发生了,所以错误代码可以知道。
  2. 使用mmap调用MAP_FIXED,在错误页面的顶部映射新的匿名页面。可选地填充数据,该数据将被访问地图的代码识别为错误的;这可能使第1步不必要。
  3. 另一种方法是在访问地图之前设置全局(或线程本地)jmp_buf,并让信号处理程序只调用longjmp

    请注意,mmaplongjmp都不是异步信号安全的,但所讨论的SIGBUS不是异步信号(尽管如果故障访问可能会被视为一个异步信号发生在非同步信号安全的库函数中,例如sscanf)。只要它是你自己的代码,而不是库函数,访问地图,你应该是安全的。并且mmap在大多数/所有实际实现中都是异步信号安全的,因此即使它在形式上不正确,您也应该在实践中使用第一个解决方案。

答案 1 :(得分:3)

最简单的方法是设置一个信号处理程序,检查对与mmap ed地址对应的内存位置的访问。

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

当你不想处理缓冲区读/写数据的复杂性时,

mmap很棒,但是由于出现问题你只会得到一种形式的错误(信号)。使用read / write机制,您可以获取errno并确定发生了什么。在这种情况下,它是开发人员的选择。

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

答案 2 :(得分:-1)

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

答案 3 :(得分:-1)

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