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

标签 c++ c linux ipc wine

有没有办法(以及如何)在 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)结构等。

  • 两台机器都创建了自己的套接字/共享内存区域(假设它们之前协商过该区域的大小)。同时,他们选择一个端口号,其中一台机器成为服务器,另一台成为客户端。连接已初始化。
  • 最初,两台机器中的所有“共享”内存都包含未初始化的数据(另一台机器对于任何给定的共享内存块可能具有不同的值)。
  • 在连接关闭之前,如果两台机器中的任何一台写入共享内存区域的任何地址,则将向另一台机器发送一条消息,其中包含更改的信息。 Linux 内核的时髦特性可能会被利用来允许原始指针与此完美配合(见下文)。然而,我不知道在 Windows 中这样做,而是通过专门的 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/

    相关文章:

    c++ - 此代码是从 vector 中添加和删除项目的线程安全方式吗?

    c++ - 如何从输入文件C++创建随机名称生成器

    c - 如何从文件名的字符串数组中读取文件?

    regex - 使用任何扩展名重命名 perl 文件

    linux - Linux 内核的哪一部分强制执行权限分离以及如何执行?

    java - 实际上,我会使用鸭子类型还是控制反转?

    android - Flutter C++ 内存分配导致光栅线程卡顿 - Android NDK Dart FFI

    c++ - UNICODE_STRING 到 wchar_t* null 终止

    c - 具有结构体和 int 的共享内存

    linux - 我怎样才能使 svnlook TreeView 只有 2 级?