code

代码

模块

代码

模块摘要

Erlang代码服务器。

描述

这个模块包含到Erlang的接口。代码服务器,它处理将编译后的代码加载到运行中的Erlang运行时系统。

运行时系统可以在嵌入式互动式模式。哪一个是由命令行标志决定的?-mode*

% erl -mode interactive

这些模式如下:

  • 在嵌入模式下,根据引导脚本在系统启动期间加载所有代码。(代码也可以稍后通过明确地命令代码服务器来加载)。

  • 在默认的交互模式下,系统启动时只加载一些代码,基本上是运行时系统所需的模块。其他代码在第一次引用时被动态加载。当调用某个模块中的函数,而该模块未加载时,代码服务器将搜索并尝试加载该模块。

为了防止不小心重装影响Erlang运行时系统模块,目录kernelstdlib以及compiler被认为是。这意味着如果用户尝试重新加载驻留在其中的模块,则系统会发出警告并拒绝该请求。该功能可以通过使用命令行标志禁用-nostick

代码路径

在交互模式下,代码服务器维护一个搜索路径,通常称为代码路径,由目录列表组成,当尝试加载模块时,它会顺序搜索这些目录。

最初,代码路径由当前工作目录和库目录下的所有erlang目标代码目录组成。$OTPROOT/lib,在哪里$OTPROOT是Erlang/OTP的安装目录,code:root_dir()目录可以命名为Name[-Vsn]默认情况下,代码服务器在具有相同版本号的目录中选择版本号最高的目录。Name.后缀-Vsn是可选的。如果ebin目录下Name[-Vsn],该目录将添加到代码路径中。

环境变量ERL_LIBS在操作系统%29中定义的%28可以用于定义更多的库目录,这些目录的处理方式与上面描述的标准OTP库目录相同,但没有ebin目录被忽略。

在附加目录中找到的所有应用程序目录都会出现在标准OTP应用程序之前,但内核和STDLIB应用程序除外,它们放在任何其他应用程序之前。换句话说,在任何附加的库目录中找到的模块覆盖OTP中同名的模块,内核和STDLIB中的模块除外。

环境变量ERL_LIBS(如果已定义)应包含以冒号分隔的(对于类Unix系统)或以分号分隔的(对于Windows)其他库的列表。

例子:

在类似Unix的系统上,ERL_LIBS可以设置为

/usr/local/jungerl:/home/some_user/my_erlang_lib

在Windows上,使用分号作为分隔符.

从存档文件加载代码

警告

从归档文件加载代码的支持是实验性的。在它准备好之前发布它的目的是获得早期的反馈。文件的格式、语义、接口等都可以在以后的版本中更改。功能lib_dir/2-code_path_choice也是实验性的。

二郎档案馆ZIP扩展名文件.ez.Erlang档案也可以放在escript文件扩展名为任意的文件。

Erlang归档文件可以包含整个Erlang应用程序或应用程序的部分。存档文件中的结构与应用程序的目录结构相同。例如,如果您创建一个mnesia-4.4.7,则必须将归档文件命名为mnesia-4.4.7.ez它必须包含一个名为mnesia-4.4.7如果省略了名称的版本部分,也必须在存档中省略。就是,mnesia.ez存档必须包含mnesia最上面的目录。

例如,应用程序的存档文件可以创建如下所示:

zip:create("mnesia-4.4.7.ez", ["mnesia-4.4.7"], [{cwd, code:lib_dir()}, {compress, all}, {uncompress,[".beam",".app"]}]).

存档中的任何文件都可以压缩,但是为了加快频繁读取的文件的访问速度,最好将其存储起来。beamapp档案中未压缩的文件。

通常,应用程序的顶部目录位于库目录中。$OTPROOT/lib或在环境变量所引用的目录中。ERL_LIBS.在启动时,当计算初始代码路径时,代码服务器还会在这些目录中查找归档文件,并可能添加ebin存档目录到代码路径。然后,代码路径包含指向以下目录的路径$OTPROOT/lib/mnesia.ez/mnesia/ebin$OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin...

代码服务器erl_prim_loader在ERTS中使用模块(可能通过erl_boot_server)从档案中读取代码文件。但是,函数erl_prim_loader也可以被其他应用程序用于从档案中读取文件。例如,调用erl_prim_loader:list_dir( "/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/examples/bench)"将列出档案内的目录内容。看erl_prim_loader(3)

应用程序存档文件和常规应用程序目录可以共存。当需要将应用程序的部分作为常规文件时,这可能很有用。一个典型的例子是priv目录,该目录必须作为常规目录驻留,以便动态链接驱动程序并启动端口程序。对于不需要此功能的其他应用程序,请选择priv可以驻留在存档和目录下的文件中。priv可读erl_prim_loader...

当一个目录被添加到代码路径中并且整个代码路径被重新设置时,代码服务器将决定应用程序中哪些子目录要从档案中读取,哪些子目录将作为常规文件读取。如果之后添加或删除目录,如果代码路径未更新(可能与以前相同的路径,以触发目录解析更新),则文件访问可能失败。

有关在应用程序存档(第二电平的每个目录ebinprivsrc,等等),如果它从存档存在,并且第二代码服务器首先选择的常规目录。函数code:lib_dir/2返回到子目录的路径。例如,code:lib_dir(megaco,ebin)可以返回的/otp/root/lib/megaco-3.9.1.1.ez/megaco-3.9.1.1/ebin时候code:lib_dir(megaco,priv)可以返回/otp/root/lib/megaco-3.9.1.1/priv

当一个escript文件包含一个档案时,对于escript可以存储在嵌入式档案中的应用程序的名称没有限制,也没有限制。单束文件也可以位于存档的顶层。启动时,嵌入式归档中的顶级目录和嵌入式归档中的所有(第二级)ebin目录都将添加到代码路径中。看erts:escript(1)

当选择代码路径中的目录时strict,在代码路径中结束的目录正是指定的目录。这意味着,例如,如果目录$OTPROOT/lib/mnesia-4.4.7/ebin显式地添加到代码路径中,则代码服务器不会从$OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin...

此行为可以通过命令行标志来控制。-code_path_choice Choice如果将国旗设置为relaxed,代码服务器将根据实际的文件结构选择合适的目录。如果正常申请ebin目录存在,它被选中。否则,目录ebin如果存在,则在存档中选择。如果两者都不存在,则选择原始目录。

命令行标志-code_path_choice Choice也会影响模块init解释boot script中的显式代码路径的解释。boot script可以strictrelaxed.将国旗设置为relaxed当使用从归档加载的代码进行详细说明时,不需要编辑boot script.默认值为relaxed.见erts:init(3)...

现行与旧法典

模块的代码可以在系统中存在两种变体:当前代码旧代码。当模块第一次加载到系统中时,模块代码将变为“当前”,并且全局导出表会更新,并引用从模块导出的所有函数。

If then a new instance of the module is loaded (for example, because of error correction), the code of the previous instance becomes 'old', and all export entries referring to the previous instance are removed. After that, the new instance is loaded as for the first time, and becomes 'current'.

模块的旧代码和当前代码都是有效的,甚至可以并发计算。不同之处在于,旧代码中导出的函数不可用。因此,不能在旧代码中对导出的函数进行全局调用,但仍然可以对旧代码进行评估,因为旧代码中的进程一直存在。

如果加载模块的第三个实例,则代码服务器将删除(清除)旧代码,并停止在其中存在的任何进程。然后第三个实例变成'当前',并且之前的当前代码变成'旧'。

有关旧代码和当前代码以及如何使进程从旧代码切换到当前代码的详细信息,请参阅Erlang Reference Manual...

参数类型和无效参数

模块和应用程序名称是原子,而文件和目录名称是字符串。由于向后兼容性的原因,一些函数同时接受字符串和原子,但是将来的版本可能只允许文档中的参数。

如果这个模块中的函数传递了一个不正确的类型(例如,一个整数或者一个元素,其中包含一个原子),那么这个模块中的函数通常会失败。如果参数类型正确,则返回错误元组,但还有其他错误(例如,指定了不存在的目录set_path/1)。

代码加载函数的错误原因

加载代码(如load_file/1)的函数将{error,Reason}在加载操作失败时返回。下面是对常见原因的描述。

badfile

对象代码的格式不正确,或者目标代码中的模块名不是预期的模块名。

nofile

没有找到带有目标代码的文件。

not_purged

无法加载目标代码,因为该代码的旧版本已经存在。

on_load_failure

模块有一个-on_load function当它被调用时失败了。

sticky_directory

对象代码驻留在一个粘稠的目录中。

数据类型

load_ret() =

{error, What ::load_error_rsn()} |

{module, Module :: module()}

load_error_rsn() =

badfile |

nofile |

not_purged |

on_load_failure |

sticky_directory

prepared_code()

一个不透明的术语,包含预先准备好的代码。

出口

set_path(Path) - > true | {错误,什么}

类型

设置目录列表的代码路径。Path...

返回:

true

如果成功

{error, bad_directory}

如果有的话Dir不是目录名。

get_path() - >路径

类型

返回代码路径。

add_path(Dir) - > add_path_ret()

add_pathz(Dir) - > add_path_ret()

类型

Dir到代码路径。该目录作为新路径中的最后一个目录添加。如果Dir路径中已经存在,因此没有添加。

返回true如果成功,或{error, bad_directory}如果Dir不是目录的名称。

add_patha(Dir) - > add_path_ret()

类型

Dir到代码路径的开头。如果Dir存在时,它将从代码路径中的旧位置中删除。

回报true如果成功,或{error, bad_directory}如果Dir不是目录的名称。

add_paths(Dirs) - >确定

add_pathsz(Dirs) - >确定

类型

中添加目录。Dirs到代码路径的末尾。如果Dir存在,但不添加。

总是回来ok,不管每个人的有效性如何Dir...

add_pathsa(Dirs) - >确定

类型

横穿Dirs并添加每个Dir到代码路径的开头。这意味着Dirs在生成的代码路径中反转。例如,如果添加[Dir1,Dir2],生成的路径将是[Dir2,Dir1|OldCodePath]...

如果Dir已经存在于代码路径中,它将从旧位置中删除。

总是回来ok,不管每个人的有效性如何Dir...

德尔[医]路径%28 NameOrDir%29->布尔值%28%29{Error,什么}

类型

从代码路径中删除目录。这个论点可以是一个原子Name,在这种情况下,具有名称的目录.../Name[-Vsn][/ebin]从代码路径中删除。另外,完整的目录名Dir可以指定为参数。

返回:

true

如果成功

false

如果找不到目录

{error, bad_name}

如果参数无效

取代[医]路径%28 Name,Dir%29->True{Error,什么}

类型

替换名为.../Name[-Vsn][/ebin]在代码路径中,使用Dir.如果Name不存在,它将添加新目录。Dir在代码路径中。新目录还必须命名为.../Name[-Vsn][/ebin]如果将目录%28库%29的新版本添加到正在运行的系统,则将使用此函数。

返回:

true

如果成功

{error, bad_name}

如果Name找不到

{error, bad_directory}

如果Dir不存在

{error, {badarg, [Name, Dir]}}

如果NameDir无效

负载[医]文件%28模块%29->load_ret()

类型

尝试加载Erlang模块。Module,使用代码路径。它查找具有与使用的Erlang机器对应的扩展名的对象代码文件,例如,Module.beam如果在目标代码中找到的模块名称与名称不同,则加载失败。Module...load_binary/3必须使用与文件名不同的模块名称加载对象代码。

回报{module, Module}如果成功,或{error, Reason}如果加载失败。见Error Reasons for Code-Loading Functions有关可能的错误原因的说明。

负载[医]ABS%28文件名%29->load_ret()

类型

load_file(Module),但是Filename绝对文件名或相对文件名。未搜索代码路径。它以与load_file/1注意到Filename不能包含扩展名%28,例如,.beam%29因为load_abs/1添加正确的扩展。

确保[医]加载%28模块%29->{模块,模块}{错误,什么}

类型

尝试以与load_file/1,除非模块已经加载。但是,在嵌入式模式下,它不会加载尚未加载但返回的模块。{error, embedded}相反。见Error Reasons for Code-Loading Functions有关其他可能的错误原因的说明。

负载[医]二进制%28模块,文件名,二进制%29->

{模块,模块}{错误,什么}

类型

此函数可用于在远程Erlang节点上加载对象代码。论辩Binary必须包含Module...Filename仅用于保存目标代码从哪个文件中保存的记录。Module来了。因此,Filename未由代码服务器打开和读取。

回报{module, Module}如果成功,或{error, Reason}如果加载失败。见Error Reasons for Code-Loading Functions有关可能的错误原因的说明。

原子[医]加载%28模块%29->确定{错误,{模块,什么}}

类型

尝试加载列表中的所有模块。Modules原子上的。这意味着,所有模块都是同时加载的,或者如果任何模块都有问题,则不会加载任何模块。

加载可能由于以下原因而失败:

badfile

对象代码的格式不正确,或者目标代码中的模块名不是预期的模块名。

nofile

不存在带有目标代码的文件。

on_load_not_allowed

模块包含-on_load function...

duplicated

一个模块包含在其中不止一次。Modules...

not_purged

无法加载对象代码,因为代码的旧版本已经存在。

sticky_directory

对象代码驻留在一个粘稠的目录中。

pending_on_load

以前加载的模块包含-on_load从未完成的函数。

如果在更改代码时尽量减少应用程序不活动的时间很重要,请使用prepare_loading/1finish_loading/1而不是atomic_load/1以下是一个例子:

{ok,Prepared} = code:prepare_loading(Modules), %% Put the application into an inactive state or do any %% other preparation needed before changing the code. ok = code:finish_loading(Prepared), %% Resume the application.

准备[医]加载%28模块%29->

{好,准备}{错误,{模块,什么}}

类型

准备加载列表中的模块。Modules.通过调用完成加载finish_loading(Prepared)...

此函数可能会失败,原因如下之一:

badfile

对象代码的格式不正确,或者目标代码中的模块名不是预期的模块名。

nofile

不存在带有目标代码的文件。

on_load_not_allowed

模块包含-on_load function...

duplicated

一个模块包含在其中不止一次。Modules...

完成[医]加载%28准备%29->确定{错误,{模块,什么}}

类型

尝试加载所有以前已准备好的模块的代码。prepare_loading/1。加载是原子式的,意味着所有模块都同时加载,或者没有加载任何模块。

此函数可能会失败,原因如下之一:

not_purged

无法加载对象代码,因为代码的旧版本已经存在。

sticky_directory

对象代码驻留在一个粘稠的目录中。

pending_on_load

以前加载的模块包含-on_load从未完成的函数。

确保[医]模块[医]加载%28模块:模块%29->

好的{错误,{模块,什么}}

类型

尝试加载列表中尚未加载的任何模块。Modules以同样的方式load_file/1...

回报ok如果成功,或{error,[{Module,Reason}]}如果某些模块加载失败。见Error Reasons for Code-Loading Functions有关其他可能的错误原因的说明。

删除%28模块%29->布尔值%28%29

类型

的当前代码。Module的当前代码Module都变老了。这意味着进程可以继续执行模块中的代码,但不能对其进行外部函数调用。

回报true如果成功,或false如果有旧代码Module必须先清除,或者如果Module不是%28加载%29模块。

清除%28模块%29->布尔值%28%29

类型

清除Module,即删除标记为旧的代码。如果一些进程仍然停留在旧代码中,这些进程将在代码被删除之前被终止。

从ERTS版本9.0开始,只有在对代码有直接引用的情况下,流程才会被认为是在代码中挥之不去。有关更多信息,请参见erlang:check_process_code/3,用于确定这一点。

回报true如果成功且需要终止任何进程,则为false...

软[医]清除%28模块%29->布尔值%28%29

类型

清除Module,也就是说,删除标记为旧的代码,但前提是没有进程在其中停留。

从ERTS版本9.0开始,只有在对代码有直接引用的情况下,流程才会被认为是在代码中挥之不去。有关更多信息,请参见erlang:check_process_code/3,用于确定这一点。

返回false如果由于旧代码中的进程而无法清除模块,则为true...

is_loaded(模块) - > {file,Loaded} | 假

类型

Filename绝对文件名。

检查Module装上子弹了。如果是的话,{file, Loaded}返回,否则false...

通常,LoadedFilename从中获取代码的绝对文件名。如果模块预装(见script(4)Loaded==preloaded。如果模块盖编译(见cover(3)Loaded==cover_compiled

all_loaded() - > {Module,Loaded}

类型

Filename绝对文件名。

返回元组列表。{Module, Loaded}所有加载模块。Loaded通常是绝对文件名,如is_loaded/1...

which(Module) -> Which

类型

如果模块未加载,此函数将搜索包含目标代码的第一个文件的代码路径。Module并返回绝对文件名。

如果加载了模块,则返回包含加载的对象代码的文件名。

如果模块是预加载的,preloaded会被归还。

如果模块是封面编译的,cover_compiled会被归还。

如果找不到模块,non_existing会被归还。

get_object_code(Module) -> {Module, Binary, Filename} | error

类型

在代码路径中搜索模块的目标代码Module.返回{Module, Binary, Filename}如果成功,否则error...Binary二进制数据对象,它包含模块的对象代码。如果要将代码加载到分布式系统中的远程节点上,这将非常有用。例如,加载模块Module在节点上Node如下所示:

... {_Module, Binary, Filename} = code:get_object_code(Module), rpc:call(Node, code, load_binary, [Module, Filename, Binary]), ...

root_dir() -> file:filename()

返回Erlang/OTP的根目录,这是安装它的目录。

例子:

> code:root_dir(). "/usr/local/otp"

lib_dir() -> file:filename()

返回库目录,$OTPROOT/lib,在哪里$OTPROOT是Erlang/OTP的根目录。

例子:

> code:lib_dir(). "/usr/local/otp/lib"

lib_dir(Name) -> file:filename() | {error, bad_name}

类型

返回应用程序的“库目录”(顶部目录)的路径。Name位于$OTPROOT/lib或在环境变量引用的目录上。ERL_LIBS...

如果在具有子目录的代码路径中调用NameName-Vsn存在常规目录ebin,则返回此目录的路径(而不是ebin目录)。

如果目录引用了存档中的一个目录,则在返回路径之前,归档名称将被剥离掉。例如,如果目录/usr/local/otp/lib/mnesia-4.2.2.ez/mnesia-4.2.2/ebin在路上,/usr/local/otp/lib/mnesia-4.2.2/ebin会被归还。这意味着应用程序的库目录是相同的,无论应用程序是否驻留在存档中。

例子:

> code:lib_dir(mnesia). "/usr/local/otp/lib/mnesia-4.2.2"

回报{error, bad_name}如果Name下的应用程序的名称。$OTPROOT/lib或在通过环境变量引用的目录上。ERL_LIBS.失败,但有例外情况:Name有错误的类型。

警告

为了向后兼容,Name也被允许为字符串。这可能会在未来的版本中改变。

lib_dir(Name,SubDir) - > file:filename()| {error,bad_name}

类型

返回直接位于应用程序顶部目录下的子目录的路径。通常,子目录位于应用程序的顶部目录下,但是当应用程序至少部分驻留在存档中时,情况就不同了。一些子目录可以作为常规目录驻留,而另一些子目录驻留在存档文件中。不检查此目录是否存在。

例子:

> code:lib_dir(megaco, priv). "/usr/local/otp/lib/megaco-3.9.1.1/priv"

异常失败,如果NameSubDir有错误的类型。

compiler_dir() - > file:filename()

返回编译器库目录。相当于code:lib_dir(compiler)...

priv_dir(名称) - > file:filename()| {error,bad_name}

类型

返回到priv应用程序中的目录。相当于code:lib_dir(Name, priv)...

警告

为了向后兼容,Name也被允许为字符串。这可能会在未来的版本中改变。

objfile_extension() - > nonempty_string()

返回与使用的Erlang机器对应的对象代码文件扩展名,即.beam...

棍子[医]DIR%28 Dir%29->ok错误

类型

标记Dir粘稠的。

返回ok如果成功,否则error...

unstick_dir(Dir) -> ok | error

类型

取消标记为粘性的目录。

如果成功则返回ok如果成功则返回,否则error

is_sticky(Module) -> boolean()

类型

返回trueif是否Module是从粘性目录加载的模块的名称(换句话说:尝试重新加载模块将失败),或者false如果Module不是加载的模块或不粘。

where_is_file(Filename) -> non_existing | Absname

类型

搜索代码路径Filename,任意类型的文件。如果找到,则返回全名。如果找不到文件,则返回non_existing。例如,该函数可用于定位应用程序资源文件。

clash() -> ok

在代码路径中的所有目录中搜索具有相同名称的模块名,并将报告写入stdout...

module_status(Module :: module()) ->

not_loaded | loaded | modified | removed

返回:

not_loaded

如果Module当前未加载。

loaded

如果Module对象文件存在并包含相同的代码。

removed

如果Module加载,但在代码路径中找不到相应的对象文件。

modified

如果Module加载,但对象文件包含具有不同MD5校验和的代码。

预加载的模块总是被报告为loaded,而不检查磁盘上的内容。封面编译的模块将始终以modified对象文件存在或removed其他方式报告。其负载路径为空字符串(这是自动生成代码的约定)的模块将仅报告为loadednot_loaded

对于已加载本机代码的模块(请参阅is_module_native/1参考资料),如果存在,则使用对象文件中本机代码的MD5总和进行比较; 该文件中的Beam代码将被忽略。相反,对于当前没有加载本机代码的模块,文件中的任何本机代码都将被忽略。

另见modified_modules/0...

modified_modules() -> module()

返回其当前加载的所有模块的列表。module_status/1回报modified.亦见all_loaded/0...

is_module_native(Module) -> true | false | undefined

类型

返回:

true

如果Module加载了本机代码的加载模块的名称。

false

如果Module已加载,但没有本机代码。

undefined

如果Module未加载

get_mode() -> embedded | interactive

返回描述代码服务器模式的原子:interactiveembedded...

当外部实体(例如IDE)为正在运行的节点提供附加代码时,此信息很有用。如果代码服务器处于交互模式,则只需将路径添加到代码。如果代码服务器处于嵌入模式,则代码必须加载load_binary/3