在D中创建命名管道?

时间:2014-11-03 07:06:25

标签: d

我试图找出D中可用于IPC的方法,主要是命名管道。我知道std.process包含来自相关进程的未命名管道的函数,尽管我更关注ipc与不相关的双向进程。我在想我可能需要最终使用本地套接字,或者查看共享内存。

有没有例子可以做到这一点?

1 个答案:

答案 0 :(得分:6)

在Unix上,您可以使用std.socket创建一个与TCP套接字类似的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();
}

他们唯一需要了解的是消息的含义(当然),以及socket的文件系统路径。

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函数原型。

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

使用该函数创建命名管道,为其提供其他进程可以使用的路径名(类似于Unix域套接字,但不在统一文件系统中)。然后使用CreateFile函数打开管道,之后,您可以像任何其他文件一样与它通信。

有两种获取函数原型的方法,因此您可以从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.有关Unicode与ANSI名称的Microsoft文档底部提到了这一点。 A版本采用ascii字符串。 W版本在D中采用utf-16,wstring。建议使用W版本,但在某些情况下A版本更容易使用。

或者,您可以从此处下载预制的win32绑定:https://github.com/AndrejMitrovic/DWinProgramming/tree/master/WindowsAPI并在构建时使用它们。

如果您只需要几个函数,我更喜欢复制/粘贴以避免依赖,但如果您正在进行大量的Windows API工作,请下载完整的绑定。

我在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库的帮助很少,你必须使用操作系统功能。但它并不难,至少在Unix上有函数原型:import 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中完成相同。