有没有办法(以及如何)在 linux 程序和通过 wine 运行的 Windows 程序之间共享内存?
由于可能很难理解为什么要做这样的事情,我给你我的情况:
我有一个只为 Windows 编译的专有程序,但这个程序有一个开放的 C 插件 API。但是,我想让我的部分代码在 native 应用程序上运行(并使用 linux 的其他库和其他优势),并以快速的方式执行 IPC
最佳答案
Wine 的目的是在 Unix(-like) 系统上提供一个类似 WinAPI 的环境。这意味着 Wine 可以被认为是一个独立的、API 外观的、“独立的”操作系统,位于类 Unix 系统之上。因此,您所说的那台机器实际上可能有两个操作系统,一个在另一个之上。第一,“真实”(控制真实硬件),即GNU/Linux。其次,在 POSIX/SUS 接口(interface)之上有称为 Wine 的 WinAPI 实现。
而且,就人类而言,只有一种可移植的方式可以在具有不同操作系统的机器之间创建进程间通信,而且您可能已经注意到,我指的是套接字。
Wine 子系统本身可以被视为半虚拟机,与 Linux 内核隔离,但同时与它紧密耦合。
为了提高效率,我的建议是使用什么套接字与我所谓的 SHMNP(共享内存网络协议(protocol))结合使用,以提供网络范围的共享内存。再次记住,两个“机器”(虽然它在物理上只是一个)应该是独立的。 Wine 实现对于笨拙的细节来说太脏了,无法轻松解决(尽管 that's nothing compared to Cygwin's hacks )。
SHMNP 以这种方式工作。但是请注意,SHMNP 不存在!这只是理论上的,并且出于明显的原因没有提供协议(protocol)结构等。
ReadNetworkShared()
和 WriteNetworkShared()
- 类似的程序。 Linux 内核特定的怪癖:
大多数现代通用硬件架构和操作系统提供了一种方法来保护内存免受用户进程的恶意/错误/意外使用。每当您读/写未映射到进程虚拟地址空间中的内存时,CPU 都会通知操作系统内核 page fault发生了。随后,内核(如果是 Unix(-like))将向违规进程发送分段违规信号,或者换句话说,您收到 SIGSEGV。
隐藏的神奇 secret 是 SIGSEGV 可能会被捕获和处理。因此,我们可以
mmap()
一些内存(共享内存区域),用 mprotect()
将其标记为只读,那么,每当我们尝试写入共享内存区域中的地址时,进程都会收到一个 SIGSEGV。信号处理程序随后在 siginfo_t
中执行检查由内核传递,并推导出两个 Action 之一。abort()
管他呢。 splice()
?)。然后,将要写入的页面标记为读/写,并设置一个计时器,以便在超时内将页面再次标记为只读,并发送旧拷贝和现在写入的页面之间的(可能是压缩的)差异通过 socket (SIMD 可以帮助你)。然后处理程序返回,允许写入(可能还有其他写入!)在没有进一步干预的情况下完成,直到计时器触发。 每当机器通过套接字接收压缩数据时,它都会被解压缩并写入它所属的位置。
希望这对你有帮助!
编辑 : 我刚刚发现了预编辑设计的一个明显缺陷。如果(压缩的)页面被发送到另一台机器,那台机器将无法区分页面内已修改的数据和未修改的数据。这涉及竞争条件,接收机器可能会丢失尚未发送的信息。然而,一些更多的 Linux 内核特定的东西修复了它。
关于c++ - 如何在通过 Wine(同一台计算机)运行的 linux 程序和 windows 程序之间共享内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32330293/