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

标签 c linux memory memory-management malloc

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

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

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

可能的解决方案:

  1. Create a temporary buffer, pass the buffer pointer to the user, on unlock copy the pixels to the actual buffer, delete the temporary buffer.

    • Pros: This is an implementable solution.
    • Cons: Performance is slow as it requires a copy which is expensive, also the memory may or may not be available. There is no way to guarantee that one temporary surface overlaps another allowing an invalidated pointer to suddenly work again.
  2. Make an additional map to a malloc'd surface and pass that to the user. On unlock, unmap the memory.

    • Pros: Very fast, no additional memory required.
    • Cons: Unknown if this is possible.
    • Gotchas: Need to set aside a reserved range of addresses are never used by anything else (including malloc or the kernel). Also need to ensure that no two surfaces overlap which could allow an old pointer to suddenly point to something valid and not seg fault when it should.
  3. Take advantage of the fact that the library does not access the memory while locked by the user and simply move the virtual address on a lock and move it back on an unlock.

    • Pros: Very fast, no additional memory required.
    • Cons: Unknown if this is possible.
    • Gotchas: Same as "2" above.

这可行吗?

附加信息:

  • This is using Linux 2.6, using stdlib.
  • The library is written in C.
  • The library and application run in user space.
  • There is a possibility of using a kernel module (to write a custom memory allocation routine), but the difficulty of writing a module in my current working climate would probably reduce the chances to near zero levels that I could actually implement this solution. But if this is the only way, it would be good to know.
  • The underlying processor is x86.

最佳答案

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

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

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

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

关于c - Linux - 从 malloc 复制虚拟内存地址或移动虚拟内存地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11618133/

相关文章:

c - stm32 上的半主机

c++ - 使用 OpenGL 和 WinAPI 跳帧?

cmake 忽略 -D CMAKE_BUILD_TYPE=Debug

C程序无法识别空格字符

c++ - 为什么 free() 没有释放我的 Arduino Uno 上的 RAM

c - 在C中使用malloc实现aligned_malloc

c++ - libcurl - 5 秒后出现奇怪的超时

linux - docker 的一个兼容性问题

c - 套接字超时实现

c - posix_memalign/memalign 做什么