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