如何在同一台计算机上通过Wine运行的Linux程序和Windows程序之间共享内存?

14
有没有一种方法(如果有,如何)在Linux程序和通过Wine运行的Windows程序之间共享内存?
由于这样做的原因可能很难理解,我向您介绍我的情况: 我有一个仅编译为Windows的专有程序,但该程序具有开放的C插件API。但是,我想让我的代码的一部分运行在本地应用程序上(并使用Linux的其他库和优势),并以快速的方式进行IPC。

如果您可以从Wine Windows进程中调用本机Linux,则可以使用shm_open - Sergei Krivonos
2个回答

9
Wine的目的是在Unix(-like)系统上提供类似WinAPI的环境。这意味着Wine可以被认为是一个独立的、以API为界面的操作系统,建立在Unix-like系统之上。因此,你所说的机器实际上可能有两个操作系统,一个在另一个之上。首先是“真正”的(控制真实硬件的)操作系统GNU/Linux。其次,就是位于POSIX/SUS接口之上的WinAPI实现,称为Wine。
就人类而言,创建跨不同操作系统的进程间通信的唯一可移植方法是使用套接字,这一点您可能已经注意到了。
Wine子系统可以被认为是一个半虚拟的机器,它与Linux内核隔离,但同时也与之紧密耦合。
为了提高效率,我的建议是使用套接字结合我所谓的SHMNP(共享内存网络协议)来提供全局共享内存。再次提醒,两个“计算机”(虽然实际上只有一个)应被视为独立的。Wine的实现太混乱了,很难轻易地解决笨拙的细节问题(尽管这与Cygwin的黑客攻击相比微不足道)。
SHMNP的工作方式如下。但请注意,SHMNP并不存在!它只是理论上的,协议结构等因明显原因未予呈现。
  • 两台机器都会创建自己的套接字/共享内存区域(假设它们事先已经协商好了区域的大小)。同时,它们选择一个端口号,一台机器成为服务器,另一台机器成为客户端。连接被初始化。

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

  • 在连接关闭之前,如果其中任何一台机器写入任何共享内存区域的地址,就会向另一台机器发送一个带有更改信息的消息。Linux内核的炫酷功能可以被利用,以使即使是原始指针也可以完美地使用(见下文)。然而,我不知道如何在Windows中通过专门的ReadNetworkShared()WriteNetworkShared()类似的过程来实现。

  • 实现可以提供某种形式的同步机制,以允许网络范围的信号量、互斥锁等。

Linux内核特定的问题: 大多数现代通用硬件架构和操作系统都提供了一种保护内存免受用户进程恶意/错误/意外使用的方法。每当您读取/写入未映射到进程虚拟地址空间中的内存时,CPU将通知操作系统内核发生了页面错误。随后,内核(如果是类Unix)将向有问题的进程发送一个分段违规信号,或者换句话说,您会收到SIGSEGV。

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

  • 如果故障地址不在共享内存区域中,abort()或其他方式。
  • 否则,待写入的页面将被复制到临时存储(可能借助于splice())。然后,将要写入的页面标记为读/写,并设置一个定时器,以便在超时时间内将页面再次标记为只读,并通过套接字发送旧副本和现在已写入页面之间的(可能压缩的)差异(SIMD 可能会对您有所帮助)。然后处理程序返回,允许写入(和可能的其他写入!)完成,直到定时器触发。

无论何时机器通过套接字接收到压缩数据,它都会被简单地解压缩并写入其所属位置。

希望这可以帮到您!

编辑:我刚刚发现预编辑设计中的一个明显缺陷。如果(压缩的)页面已发送到另一台机器,则该另一台机器将无法区分已在页面中修改和未修改的数据。这涉及到一种竞争条件,其中接收机器可能会丢失尚未发送的信息。但是,一些更多的 Linux 内核特定的东西可以解决这个问题。


7
我不确定这是否是一个好主意,或者它是否会起作用,但你可以在/dev/shm中创建文件,并从Wine和本地Linux应用程序访问它们。请注意,这不是一定存在的,所以你应该有备用的IPC方法。

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

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

2
我点赞了你的解决方案,因为我使用了它,但我验证了另一个答案,因为它提供了更多细节,帮助我决定使用内存文件系统,这是特定于此情况的,因为Wine通过主机libc访问文件。 - hl037_

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接