简短问题:
是否有可能将malloc的缓冲区映射为具有访问同一缓冲区的两种方式(指向同一物理内存的两个指针)?
或者,是否可以临时移动malloc收到的虚拟内存地址?或者是否可以从虚拟空间中的一个位置指向另一个位置?
背景
我正在使用DirectFB
,一个表面管理和2D图形堆肥库。我试图强制执行锁定协议,即锁定表面,仅在锁定时修改内存(指针指向使用malloc分配的系统内存),并解锁表面。
我目前正在尝试追踪一个应用程序中的错误,该应用程序锁定表面,然后存储像素指针并稍后修改表面。这意味着库不知道何时可以安全地读取或写入曲面。我试图找到一种方法来检测锁定协议是否已被违反。我想要的是在解锁调用之后使传递给用户的指针无效的方法。更好的是,如果它在锁定后尝试访问内存,我希望应用程序能够出错。这将在调试器中停止并让我们知道涉及哪个表面,涉及哪个例程,谁调用它等等。
可能的解决方案:
创建一个临时缓冲区,将缓冲区指针传递给用户,解锁时将像素复制到实际缓冲区,删除临时 缓冲液中。
- 优点:这是一个可实施的解决方案。
- 缺点:性能很慢,因为它需要昂贵的副本,内存可能也可能不可用。没有 保证一个临时表面与另一个临时表面重叠的方法 一个无效的指针突然再次工作。
为malloc表面制作一个额外的地图并将其传递给用户。解锁后,取消映射内存。
- 优点:速度非常快,无需额外内存。
- 缺点:如果可能,则为未知。
- 陷阱:需要预留一个保留的地址范围,其他任何地方(包括malloc或内核)都不会使用。还需要 确保没有两个表面重叠,这可能允许旧指针 突然指出一些有效的东西而不是它应该的错误。
- 醇>
利用库在用户锁定时不访问内存并简单地移动虚拟地址的事实 锁定并在解锁时将其移回。
- 优点:速度非常快,无需额外内存。
- 缺点:如果可能,则为未知。
- 陷阱:与上面的“2”相同。
这可行吗?
其他信息:
- 这是使用
Linux 2.6
,使用 stdlib 。- 该库以
C
编写。- 库和应用程序在用户空间中运行。
- 有可能使用内核模块(编写自定义内存分配例程),但编写模块的难度 我目前的工作环境可能会减少接近的机会 我可以实际实现此解决方案的零级别。但如果这样 是唯一的方式,知道这一点很好。
- 底层处理器为
x86
。
答案 0 :(得分:5)
您要为页面创建多个映射的函数是shm_open
。
您可能只在一个进程中使用内存,但它仍然是“共享内存” - 也就是说,将存在同一底层物理页面的多个虚拟映射。
然而,这不是你想要做的。你应该做的是让你的锁定函数使用mprotect
系统调用来解锁时内存不可读并恢复锁定权限;没有锁定的任何访问将导致段错误。当然,这只能用于同时访问一个线程...
追踪问题的另一种可能更好的方法是在valgrind
或其他内存分析工具中运行您的应用程序。这将大大减慢它,但允许你非常好的控制:你可以有一个valgrind脚本,将内存标记/取消标记为可访问,工具将在发生违规时直接进入调试器。但对于像这样的一次性解决问题,我想在你的锁定/解锁函数中安装一个#ifdef DEBUG
- 包裹mprotect
来电。