【问题标题】:Erlang NIF from single process storing structs in memoryErlang NIF 来自单个进程在内存中存储结构
【发布时间】:2013-01-03 02:58:48
【问题描述】:

我正在编写一个 Erlang C NIF,它只会被一个 Erlang 进程使用。我想创建一个包含指针数组的结构。我需要它存在于进程对 NIF 的调用之间。

我需要了解的是从 Erlang NIF 方面执行此方法的正确方法。我正在考虑在所有函数之外编写一个结构,以便所有人都可以访问它。当我在对 NIF 的一次调用中创建它,然后返回并在对 NIF 的另一次调用中使用它时,它似乎工作得很好。

我担心这可能是因为进程停留在调度线程的本地,因此不必在内存中移动结构和底层数组。

我应该在函数中使用 erlang:memalloc 并避免一起使用全局变量,还是保持原样使用全局结构?

可能返回一个指向包含我所有数据的单个数组的指针?

【问题讨论】:

    标签: c memory erlang erlang-nif


    【解决方案1】:

    您当然可以返回一个指向包含您的数据的单个数组的指针;为此,请查看ErlNifResourceType。您将把它传回给调用erlang进程,然后它会在随后的NIF调用中将它传回给您。这将确保一次只有一个线程对您的数据进行操作(假设只有一个进程拥有该资源的副本;这不是您想要共享的东西,尤其是在它包含指针的情况下)。

    您也可以将其编码为 erlang 列表,但这可能会非常低效。

    话虽如此,您可以使用来自 NIF 的共享内存。例如,这是一个使用共享数据实现为 NIF 的 ets-like database

    您只需要记住您正在访问共享资源。 NIF API 提供thread creationthread specific datamutexesconditionsread/write locks。您甚至可以从 NIF 创建的线程向 erlang 进程发送消息(在长时间运行的 NIF 调用的情况下,这实际上是您希望实现它以防止调度问题的方式)。

    根据您的要求,您最好使用 ErlNifResource 类型,而不是使用多线程和共享资源控制。从技术上讲,如果您只使用一个 erlang 进程,则可以将其保留为全局变量(阅读:共享资源),而不会产生任何有害的副作用。话虽如此,事情会发生变化,当某人尝试从多个进程中使用您的代码时,您不希望成为他们头疼的原因。无论您最终使用哪种方法,请确保它是线程安全的。

    【讨论】:

    • 能否详细说明运行时共享资源在erlang内存中的位置?
    • NIF 是动态链接库,因此它们使用调用进程的内存(操作系统可能会进行一些管理以防止多个应用程序加载同一个库)。给它,就像 C 一样。所有线程共享一个公共堆,这是任何动态分配的对象所在的地方。至于全局变量,它是特定于系统的:一些系统将它们分配在堆上,一些将它们分配在堆栈上,还有一些将它们完全分配到其他地方。这里有一个很好的细分:stackoverflow.com/questions/1169858/…
    • 简短回答:您不必担心从不同的调度线程调用您的 NIF;如果变量是静态成员变量或全局变量,它将可以从所有调度程序线程访问。
    • 那么 enif_alloc_resource 的目的仅仅是为了能够将指针返回给 Erlang 以允许 GC 吗?没有必要让 enif_alloc 仅在返回 Erlang 时有用,但持续共享内存空间是必要的吗?
    • enif_alloc_resource 的目的是让您能够声明可以传递回 erlang 的本机类型,并定义其构造函数/析构函数。如果您的资源包含指针,您仍然必须销毁它们明确指向的对象从析构函数; ErlNifResources 的唯一真正好处是您可以将它们传递回 VM 中的进程。 enif_alloc 与 enif_alloc_resource 不同; enif_alloc 基本上是 malloc 的替代品。对于使用不需要传回 VM 的共享内存的 NIF 很有用。
    猜你喜欢
    • 2013-01-03
    • 2016-07-19
    • 1970-01-01
    • 2015-01-02
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多