Linux - 从malloc复制虚拟内存地址或移动虚拟内存地址

时间:2012-07-23 18:17:07

标签: c linux memory memory-management malloc

简短问题:
是否有可能将malloc的缓冲区映射为具有访问同一缓冲区的两种方式(指向同一物理内存的两个指针)? 或者,是否可以临时移动malloc收到的虚拟内存地址?或者是否可以从虚拟空间中的一个位置指向另一个位置?

背景
我正在使用DirectFB,一个表面管理和2D图形堆肥库。我试图强制执行锁定协议,即锁定表面,仅在锁定时修改内存(指针指向使用malloc分配的系统内存),并解锁表面。

我目前正在尝试追踪一个应用程序中的错误,该应用程序锁定表面,然后存储像素指针并稍后修改表面。这意味着库不知道何时可以安全地读取或写入曲面。我试图找到一种方法来检测锁定协议是否已被违反。我想要的是在解锁调用之后使传递给用户的指针无效的方法。更好的是,如果它在锁定后尝试访问内存,我希望应用程序能够出错。这将在调试器中停止并让我们知道涉及哪个表面,涉及哪个例程,谁调用它等等。

可能的解决方案:

  
      
  1. 创建一个临时缓冲区,将缓冲区指针传递给用户,解锁时将像素复制到实际缓冲区,删除临时   缓冲液中。

         
        
    • 优点:这是一个可实施的解决方案。
    •   
    • 缺点:性能很慢,因为它需要昂贵的副本,内存可能也可能不可用。没有   保证一个临时表面与另一个临时表面重叠的方法   一个无效的指针突然再次工作。
    •   
  2.   
  3. 为malloc表面制作一个额外的地图并将其传递给用户。解锁后,取消映射内存。

         
        
    • 优点:速度非常快,无需额外内存。
    •   
    • 缺点:如果可能,则为未知。
    •   
    • 陷阱:需要预留一个保留的地址范围,其他任何地方(包括malloc或内核)都不会使用。还需要   确保没有两个表面重叠,这可能允许旧指针   突然指出一些有效的东西而不是它应该的错误。
    •   
  4.   
  5. 利用库在用户锁定时不访问内存并简单地移动虚拟地址的事实   锁定并在解锁时将其移回。

         
        
    • 优点:速度非常快,无需额外内存。
    •   
    • 缺点:如果可能,则为未知。
    •   
    • 陷阱:与上面的“2”相同。
    •   
  6.   

这可行吗?

其他信息:

  
      
  • 这是使用Linux 2.6,使用 stdlib
  •   
  • 该库以C编写。
  •   
  • 库和应用程序在用户空间中运行。
  •   
  • 有可能使用内核模块(编写自定义内存分配例程),但编写模块的难度   我目前的工作环境可能会减少接近的机会   我可以实际实现此解决方案的零级别。但如果这样   是唯一的方式,知道这一点很好。
  •   
  • 底层处理器为x86
  •   

1 个答案:

答案 0 :(得分:5)

您要为页面创建多个映射的函数是shm_open

您可能只在一个进程中使用内存,但它仍然是“共享内存” - 也就是说,将存在同一底层物理页面的多个虚拟映射。

然而,这不是你想要的。你应该做的是让你的锁定函数使用mprotect系统调用来解锁时内存不可读并恢复锁定权限;没有锁定的任何访问将导致段错误。当然,这只能用于同时访问一个线程...

追踪问题的另一种可能更好的方法是在valgrind或其他内存分析工具中运行您的应用程序。这将大大减慢它,但允许你非常好的控制:你可以有一个valgrind脚本,将内存标记/取消标记为可访问,工具将在发生违规时直接进入调试器。但对于像这样的一次性解决问题,我想在你的锁定/解锁函数中安装一个#ifdef DEBUG - 包裹mprotect来电。