Erlang运行时系统( Erlang Run-Time System,ERTS )有一些用C语言编写的驱动程序,用于与操作系统交互或访问低级资源,据我所知,ERTS在启动时编译这些驱动程序以准备从Erlang代码加载,驱动程序inet_drv.c就是其中之一,它用于处理网络任务,如创建套接字、侦听或接受新的传入连接。
我想手动测试这个驱动程序,以了解ERTS的默认行为,并了解如何在将来高效地实现驱动程序。我跟踪Erlang手册引用来实现驱动程序:首先用OS C语言编译器编写和编译驱动程序,第二次使用erl_ddll模块从erlang代码加载驱动程序,最后通过生成的Erlang进程链接到驱动程序,所以这非常简单和容易。
因此,我尝试使用驱动程序inet_drv.c执行以下步骤,然后搜索并尝试用Compiler编译它,Compiler是FreeBSD系统的默认C编译器:
cc inet_drv.c在此之后,出现了一个错误,即没有定义文件erl_driver.h,该头文件在驱动程序的代码中用作包含的文件(#include<erl_driver.h>),因此我搜索它并使用-I选项将它的目录路径添加到cc命令中,让编译器搜索该目录中包含的文件,然后重新编译它:
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语言编译器,并且应该像我一样添加包含的头文件,那么为什么当我尝试这样做时,它不能工作呢?
发布于 2021-11-12 16:25:00
首先要做的是:
据我所知,ERTS在引导时编译这些驱动程序。
不,ERTS不编译驱动程序。inet_drv.c作为Erlang/OTP的一部分编译,并链接到beam.smp二进制文件中。
inet_drv不是典型的驱动程序。引用文档的如何实现驱动程序部分:
驱动程序可以作为共享库(在Windows上称为DLL )动态加载,或者在编译和链接时以静态方式与模拟器链接。这里只描述了动态加载的驱动程序,静态链接驱动程序超出了本节的范围。
inet_drv是一个静态加载的驱动程序,因此不需要使用erl_ddll加载。
继续编译错误。在运行make时,所有编译器参数都会自动添加,因此,如果需要手动调用编译器,最好检查make生成的命令行并从此开始。让我们看看Debian Erlang包的构建日志。在搜索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为您生成的命令行开始就会容易得多。
https://stackoverflow.com/questions/69945022
复制相似问题