如何通过Wine(同一台计算机)在linux程序和windows程序运行之间共享内存?

How to share memory between linux program and windows program running through Wine (same computer)?

有没有办法(以及如何)通过 wine 在 linux 程序和 windows 程序 运行 之间共享内存?

既然很难理解为什么要这样做,我给你我的情况: 我有一个专为 windows 编译的专有程序,但这个程序有一个开放的 C 插件 API。但是,我想在本机应用程序上制作我的部分代码 运行(并使用其他库和 linux 的其他优势),并快速执行 IPC

我不确定这是个好主意或者它是否可行,但您可以在 /dev/shm 中创建文件并从 Wine 和您的本机 Linux 应用程序访问它们。

不能保证存在,所以你应该有一个后备 IPC 方法。

https://superuser.com/questions/45342/when-should-i-use-dev-shm-and-when-should-i-use-tmp

否则,您可以尝试构建一个可以从 Linux: http://web.archive.org/web/20150225173552/http://wine-wiki.org/index.php/WineLib#Calling_a_Native_Windows_dll_from_Linux 调用您的 Windows 代码的 winelib 应用程序。我也不确定它是否有效。

Wine 的目的是在 Unix(类)系统上提供一个类 WinAPI 的环境。这意味着 Wine 可以被认为是一个独立的、API-facaded、"independent" 操作系统,位于类 Unix 系统之上。因此,您所说的那台机器实际上可能有两个操作系统,一个在另一个之上。首先,"real"(控制真实硬件),即GNU/Linux。其次,在 POSIX/SUS 接口之上有一个名为 Wine 的 WinAPI 实现。

而且,就人类而言,只有一种可移植的方式可以在具有不同操作系统的机器之间创建进程间通信,而且,您可能已经注意到,我指的是套接字。

Wine 子系统本身可以被认为是半虚拟机,与 Linux 内核隔离,但同时与它紧密耦合。

为了提高效率,我的建议是结合使用什么套接字和我所说的 SHMNP(共享内存网络协议)来提供网络范围的共享内存。同样,请记住,"machines"(尽管它在物理上只是一个)应该是独立的。 Wine 实现对于笨拙的细节来说太脏了,无法轻松解决(尽管 that's nothing compared to Cygwin's hacks)。

SHMNP 就是这样工作的。但是请注意,SHMNP 存在!这只是理论上的,协议结构 出于显而易见的原因没有给出。

  • 两台机器都创建了它们自己的 sockets/shared-memory 区域(假设它们之前协商了区域的大小)。同时,他们选择一个端口号,其中一台机器成为服务器,另一台机器成为客户端。连接已初始化。

  • 最初,两台机器中的所有 "shared" 内存都包含未初始化的数据(另一台机器对于任何给定的共享内存块可能具有不同的值)。

  • 在连接关闭之前,如果两台机器中的任何一台向共享内存区的任意地址写入数据,都会向另一台机器发送一条消息,将改变的信息发送给另一台机器。 Linux 内核的 funky 特性可能会被利用来允许原始指针与此完美配合(见下文)。然而,我不知道在 Windows 中做这件事,而是通过专门的 ReadNetworkShared()WriteNetworkShared() 之类的程序。

  • 实现可能会提供某种同步机制,因此允许网络范围内的信号量、互斥量、.

Linux 内核特有的怪癖: 大多数现代通用硬件架构和操作系统都提供了一种方法来保护内存不被用户进程 malicious/buggy/unintended 使用。每当您 read/write 到未映射到进程虚拟地址 space 中的内存时,CPU 将通知操作系统内核发生了 page fault。随后,内核(如果是 Unix(-like))将向违规进程发送分段违规信号,或者换句话说,您会收到 SIGSEGV。

隐藏的神奇秘密是可以捕获并处理 SIGSEGV。因此,我们可以 mmap() 一些内存(共享内存区域),用 mprotect() 将其标记为只读,然后,每当我们尝试写入共享内存区域中的地址时,进程将收到 SIGSEGV。信号处理程序随后在内核传递的 siginfo_t 中执行检查,并推断出两个操作之一。

  • 如果错误地址不是在共享内存区,abort()或其他。
  • 否则,将要写入的页面复制到临时存储中(也许借助splice()?)。然后,将要写入的页面标记为read/write,并设置一个计时器,以便在超时时间内将页面再次标记为只读,并且(可能压缩)旧副本和现在写入的页面之间的差异通过套接字发送(SIMD 可能会在这里帮助你)。处理程序然后 returns,允许写入(可能还有其他写入!)在计时器触发之前无需进一步干预即可完成。

每当机器通过套接字接收到压缩数据时,它就会简单地解压缩并写入它所属的位置。

希望对您有所帮助!

编辑: 我刚刚发现预编辑设计的一个明显缺陷。如果将(压缩的)页面发送到另一台机器,那台机器将无法区分页面中已修改的数据和未修改的数据。这涉及竞争条件,接收机器可能会丢失尚未发送的信息。然而,更多 Linux-kernel-specific 的东西修复了它。