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

问题描述:

短的问题:
是否有可能映射已malloc分配有两种方式,缓冲液(两个指针指向相同的物理内存)访问相同的缓冲区? 或者,是否有可能临时移动malloc接收到的虚拟内存地址?或者是否有可能从虚拟空间中的一个位置指向另一个位置?Linux的 - 从malloc的复制虚拟内存地址或移动虚拟内存地址

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

我目前正试图追踪锁定表面的应用程序中的错误,然后存储像素指针并稍后修改表面。这意味着图书馆不知道何时读取或写入表面是安全的。我试图找到一种方法来检测锁定协议已被违反。我想要的是在解锁调用完成后,传递给用户的指针无效。更好的是,如果应用程序试图在锁定后访问内存,我希望应用程序将其分割为错误。这将停止在调试器,并给我们一个想法,表面是参与,参与该程序中,谁把它称为等

可能的解决方案:

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

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

    • 优点:非常快,不需要额外的内存。
    • 缺点:如果可能的话,未知。问题:需要预留一个保留范围的地址,而不会被其他任何东西(包括malloc或内核)使用。还需要 确保没有两个表面重叠,这可能会允许旧指针 突然指向某个有效的内容,而不是当它应该时指向seg故障。的事实,而由用户锁定,只是继续前进 锁定虚拟地址和将其移回上一个解锁库不访问存储器
  3. 利用。

    • 优点:非常快,不需要额外的内存。
    • 缺点:如果可能的话,未知。
    • 问题:与上面的“2”相同。

这是可行的?

附加信息:

  • 这是使用Linux 2.6,使用STDLIB
  • 该图书馆编写于C
  • 库和应用程序在用户空间中运行。有可能使用内核模块(编写自定义的内存分配例程),但是在我目前的工作环境中编写模块的难度可能会减少我可以实际实现的零水平附近的机会此解决方案。但是如果这个 是唯一的方法,这将是很好的知道。
  • 底层处理器是x86
+0

你想要一个内存范围的副本,或者你只是想要第二个指针吗? – steffen 2012-07-23 18:20:56

+0

我想要一个指向它的第二个指针,这个指针可以在Unlock调用时失效。 – user1539433 2012-07-23 19:57:30

+0

这应该是可能的......我认为它通常用于像循环缓冲区这样的事情(其中缓冲区在内存中依次映射两次,所以任何达到完全缓冲区大小的读/写都可以是单个'memcpy')。 – 2012-07-23 20:44:18

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

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

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

另一种可能更好的方式来跟踪问题将是运行您的应用程序在valgrind或另一个内存分析工具。这会大大降低速度,但可以很好地控制:您可以使用valgrind脚本来标记/取消标记内存为可访问状态,并且该工具会在发生违规时直接将您踢入调试器。但是对于像这样一次性解决问题,我会说在您的锁定/解锁功能中安装一个包含#ifdef DEBUG的包裹mprotect调用。

+0

我不知道mprotect。感谢您的建议。 mprotect唯一的问题是该库仍然需要访问内存。该库当然有一个内部锁定机制,它也可以使用mprotect(这会比目前做的更好),但是当图书馆表面被锁定时,应用程序仍然会潜入一个机会窗口。我将不得不考虑你的valgrind想法,但我担心它可能有类似的机会之窗。 – user1539433 2012-07-23 20:01:12

+0

@ user1539433您可以注册一个检查当前堆栈跟踪的故障处理程序,并且如果它导致库自己的内部存取器方法,则会丢弃SEGV。这可以使用'mprotect'或valgrind脚本。 – Borealid 2012-07-24 13:09:06