【问题标题】:How to implement Erlang Driver As Default efficient Implementation如何将 Erlang Driver 实现为默认高效实现
【发布时间】:2021-12-24 22:13:40
【问题描述】:

Erlang 运行时系统 (ERTS) 有一些用 C 语言编写的驱动程序,用于与操作系统交互或访问低级资源,据我所知,ERTS 在启动时编译这些驱动程序以准备加载从 Erlang 代码来看,驱动程序 inet_drv.c 是这些驱动程序之一,它用于处理网络任务,例如创建套接字和侦听或接受新的传入连接。

我想手动测试此驱动程序以大致了解 ERTS 的默认行为并了解将来如何有效地实现驱动程序,我跟踪了 Erlang Manual Reference to implementation drivers 说:首先编写和编译通过 OS C 语言编译器的驱动程序,第二次使用 erl_ddll 模块从 erlang 代码加载驱动程序,最后通过衍生的 Erlang 进程链接到驱动程序,所以这非常简单易行。

所以我用驱动程序inet_drv.c 尝试了这些步骤,我搜索了它并尝试使用 Clang 编译器编译它,它是 FreeBSD 系统的默认 C 编译器:

cc inet_drv.c

之后有一个错误说文件erl_driver.h没有定义,这个头文件在驱动程序的代码中被用作包含文件(#include<erl_driver.h>)所以我搜索它并将它的目录路径添加到cc 命令使用-I 选项让编译器在此目录中搜索包含的文件,然后我重新编译它:

cc inet_drv.c -I/usr/ports.... 

之后,有另一个未定义的文件,所以我做了 5 或 6 次相同的事情,最后,我为包含的文件添加了所有需要的路径,结果是这个命令:

cc inet_drv.c

-I/usr/ports/lang/erlang/work/otp-OTP-21.3.8.18/erts/emulator/beam

-I/usr/local/lib/erlang/usr/include

-I/usr/ports/lang/erlang/work/otp-OTP-21.3.8.18/erts/emulator/sys/unix

-I/usr/ports/lang/erlang/work/otp-OTP-21.3.8.18/erts/include/internal

-I/usr/ports/lang/erlang/work/otp-OTP-21.3.8.18/erts/emulator/sys/common

-I/usr/ports/lang/erlang/work/stage/usr/local/lib/erlang/erts-10.3.5.14/include/internal

我对结果感到惊讶:13 个错误和 7 个警告,shell 输出以及错误和警告描述在下面的链接中。 我的问题是:为什么会出现这些错误?我做错了什么?

由于此驱动程序可以完美地响应 ERTS 网络任务,因此它由 ERTS 编译而没有错误,并且 ERTS 应该使用默认为 Clang 的 OS C 语言编译器,并且应该像我一样添加包含的头文件,所以为什么当我尝试这样做时这不起作用?

https://ibb.co/bbtFHZ7

https://ibb.co/sF8QsDx

https://ibb.co/Lh9cDCH

https://ibb.co/W5Gcj7g

【问题讨论】:

    标签: c erlang elixir freebsd erlang-otp


    【解决方案1】:

    第一件事:

    据我所知,ERTS 在启动时编译这些驱动程序

    不,ERTS 不编译驱动程序。 inet_drv.c 被编译为 Erlang/OTP 的一部分并链接到 beam.smp 二进制文件中。

    inet_drv 不是典型的驱动程序。引用文档的How to Implement a Driver 部分:

    驱动程序可以动态加载,作为共享库(在 Windows 上称为 DLL),或静态加载,在编译和链接时与模拟器链接。此处仅描述动态加载的驱动程序,静态链接的驱动程序超出了本节的范围。

    inet_drv 是静态加载的驱动程序,因此不需要使用erl_ddll 加载。


    关于编译错误。当您运行make 时,所有编译器参数都会自动为您添加,因此如果您需要手动调用编译器,最好检查make 生成的命令行并从那里开始。让我们看看the build log for the Debian Erlang package。搜索inet_drv 我们得到这个命令行(添加了换行符):

    x86_64-linux-gnu-gcc -Werror=undef -Werror=implicit -Werror=return-type  -fno-common \
      -g -O2 -fno-strict-aliasing -I/<<PKGBUILDDIR>>/erts/x86_64-pc-linux-gnu    -D_GNU_SOURCE \
      -DHAVE_CONFIG_H -Wall -Wstrict-prototypes -Wpointer-arith -Wmissing-prototypes \
      -Wdeclaration-after-statement -DUSE_THREADS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS \
      -D_POSIX_THREAD_SAFE_FUNCTIONS   -DBEAMASM=1 -DLIBSCTP=libsctp.so.1 \
      -Ix86_64-pc-linux-gnu/opt/jit -Ibeam -Isys/unix -Isys/common -Ix86_64-pc-linux-gnu \
      -Ipcre -I../include -I../include/x86_64-pc-linux-gnu -I../include/internal \
      -I../include/internal/x86_64-pc-linux-gnu -Ibeam/jit -Ibeam/jit/x86 -Idrivers/common \
      -Idrivers/unix -c \
      drivers/common/inet_drv.c -o obj/x86_64-pc-linux-gnu/opt/jit/inet_drv.o
    

    由于您是在 FreeBSD 上构建的,因此其中一些会有所不同,但原则是不变的 - 大多数时候您只想运行 make 而不是直接调用编译器,但如果您需要调用编译器,从make为你生成的命令行开始会容易得多。

    【讨论】:

    • 谢谢 我理解这个想法,这意味着在安装 Erlang/OTP 作为其中一部分时,Erlang 的默认驱动程序只编译一次?
    • 也谢谢你的链接,我注意到DHAVE_CONFIG_Hinet_drv.c 我们有:ifdef HAVE_CONFIG_H #include "config.h" #endif 所以在我的命令中没有包含文件config.h
    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 2011-04-29
    • 2018-12-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2012-06-24
    相关资源
    最近更新 更多