我试图弄清楚D中IPC有哪些可用的方法,主要是命名管道。我知道std.process包含用于来自相关进程的未命名管道的函数,尽管我更多地关注具有双向不相关进程的ipc。我当时以为我可能需要结束使用本地套接字,或者查看共享内存。

有没有这样做的例子?

最佳答案

在Unix上,您可以使用与TCP套接字类似的std.socket创建unix域套接字,但仅限本地。这是一些示例代码:

 // SERVER
import std.socket;
void main() {
    auto listener = new Socket(AddressFamily.UNIX, SocketType.STREAM);
    listener.bind(new UnixAddress("/home/me/uds"));
    listener.listen(10);

    /*while(1)*/ {
        auto soc = listener.accept();
        soc.send("cool\n");
        soc.close();
    }

    listener.close();

    import core.sys.posix.unistd;
    unlink("/home/me/uds");
}

和客户:
void main() {
    auto soc = new Socket(AddressFamily.UNIX, SocketType.STREAM);
    soc.connect(new UnixAddress("/home/me/uds"));

    import std.stdio;
    char[1222] buf;
    writeln(buf[0 .. soc.receive(buf)]);
    soc.close();
}

他们彼此之间唯一需要了解的是消息的含义(当然),以及套接字的文件系统路径。

Unix也有命名管道,但是它们不是像unix域套接字(或Windows命名管道)那样双向的。

如果确实要使用unix命名管道,则将它们称为FIFO文件,并使用mkfifo系统API函数进行制作。您可以使用import core.sys.posix.sys.stat;访问它,然后以与C中相同的方式使用它:将其传递给字符串和模式以创建文件,别忘了检查返回值,然后使用常规的Unix文件功能对其进行读取/写入,例如readwriteclose都来自import core.sys.posix.unistd;。有关这些功能,请参阅C文档。 man 2 readman 3 mkfifo(如果您使用的是Linux),或者只是在网上搜索这些页面。

但是我认为unix域套接字是您正在寻找的东西,它的工作原理与任何其他套接字基本相同,如上面的示例所示。

Windows的处理方式有所不同,D标准库甚至不包含OS API函数原型(prototype)。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365150%28v=vs.85%29.aspx

您可以使用该函数创建一个命名管道,并为其指定其他进程可以使用的路径名(类似于Unix域套接字,但不在统一文件系统中)。然后,您可以使用CreateFile函数打开管道,然后,您可以像其他任何文件一样对其进行交谈。

有两种获取函数原型(prototype)的方法,因此您可以从D调用这些函数。一种方法是自己复制/粘贴它们,如下所示:
    extern(Windows)
    HANDLE CreateNamedPipeA(
            LPCTSTR lpName,
            DWORD dwOpenMode,
            DWORD dwPipeMode,
            DWORD nMaxInstances,
            DWORD nOutBufferSize,
            DWORD nInBufferSize,
            DWORD nDefaultTimeOut,
            LPSECURITY_ATTRIBUTES lpSecurityAttributes
    );

首先,使用import core.sys.windows.windows;获取基本的Windows类型定义,然后将类似的样式添加到文件中。它与MSDN相同,只是删除了In之类的内容。 (您也可以将它们也更改为D的in关键字)。

最大的事情是名称中添加了A或W。这是在Microsoft文档底部有关Unicode和ANSI名称的内容中提到的。 A版本采用ascii字符串。 W版本采用utf-16,D中为wstring。建议使用W版本,但在某些情况下使用A版本会更容易一些。

或者,您可以从以下位置下载预制的Win32绑定(bind):https://github.com/AndrejMitrovic/DWinProgramming/tree/master/WindowsAPI并在构建时使用它们。

如果您只需要几个函数,我更喜欢复制/粘贴以避免依赖,但是如果您要执行许多Windows API工作,请下载完整的绑定(bind)。

我用D编写了一个跨平台的终端仿真器,它使用了以下技术:https://github.com/adamdruppe/terminal-emulator

可分离部分使用unix域套接字服务器:
https://github.com/adamdruppe/terminal-emulator/blob/master/detachable.d

可连接部分是UDS客户端
https://github.com/adamdruppe/terminal-emulator/blob/master/attach.d

Windows仿真器核心使用专门的命名管道来执行我自己的异步“匿名”管道,而不是您的用例,但是显示了如何调用函数:
https://github.com/adamdruppe/terminal-emulator/blob/master/terminalemulator.d

共享内存是您可以做的另一件事,但是D库几乎没有帮助,您必须使用OS函数。但这并不难,至少在Unix上有函数原型(prototype):导入core.sys.posix.sys.shm并使用与C中相同的函数。

我从未在Windows上实际执行过此操作,但是快速搜索说,您可以只创建一个内存映射文件:http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551%28v=vs.85%29.aspx

也许,也许也许会得到phobos的帮助:http://dlang.org/phobos/std_mmfile.html,但我从未真正尝试过这种方法。当我需要共享内存时,我只是执行了shmget等Unix函数(这在我的simpledisplay.d https://github.com/adamdruppe/arsd/blob/master/simpledisplay.d中,它使用它与X服务器通信)。

最重要的是,Unix域套接字与TCP套接字基本相同,而Phobos的std.socket可以提供帮助。

其他所有操作都与在C中相同。

关于d - 在D中创建命名管道?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26709356/

10-15 18:30