查看源代码 内核应用

描述

内核应用程序拥有运行 Erlang 运行时系统所需的所有代码:文件服务器、代码服务器等等。

内核应用程序是第一个启动的应用程序。它是强制性的,因为基于 Erlang/OTP 的最小系统由 Kernel 和 STDLIB 组成。 Kernel 包含以下功能区域

  • 应用程序的启动、停止、监督、配置和分布
  • 代码加载
  • 日志记录
  • 全局命名服务
  • Erlang/OTP 的监督
  • 与套接字的通信
  • 操作系统接口

日志处理器

内核应用程序中定义了两个标准日志处理器。 这些在 内核用户指南 以及 logger_std_hlogger_disk_log_h 手册页中进行了描述。

操作系统信号事件处理器

可以通过内核应用程序的事件管理器订阅异步操作系统信号(请参阅 OTP 设计原则gen_event),注册为 erl_signal_server。安装了默认的信号处理程序,该处理程序处理以下信号

  • sigusr1 - 默认处理程序将停止 Erlang 并生成一个带有口号“Received SIGUSR1”的崩溃转储。 这等效于调用 erlang:halt("Received SIGUSR1")

  • sigquit - 默认处理程序将立即停止 Erlang。 这等效于调用 erlang:halt()

  • sigterm - 默认处理程序将正常终止 Erlang。 这等效于调用 init:stop()

事件

添加到 erl_signal_server 的任何事件处理程序都必须处理以下事件。

  • sighup - 在控制终端上检测到挂起或控制进程死亡

  • sigquit - 从键盘退出

  • sigabrt - 来自中止的中止信号

  • sigalrm - 来自警报的定时器信号

  • sigterm - 终止信号

  • sigusr1 - 用户定义的信号 1

  • sigusr2 - 用户定义的信号 2

  • sigchld - 子进程停止或终止

  • sigstop - 停止进程

  • sigtstp - 在终端键入的停止

os:set_signal/2 中描述了设置操作系统信号。

配置

为 Kernel 应用程序定义了以下配置参数。 有关配置参数的更多信息,请参阅文件 app

  • connect_all = true | false - 如果启用 (true),这也是默认值,则 global 将主动连接到所有已知节点。 请注意,您还需要启用 prevent_overlapping_partitions,以便 global 确保维护完全连接的网络。prevent_overlapping_partitions 还可以防止 global 的名称注册和锁定出现不一致。

    现在已弃用的命令行参数 -connect_all <boolean>connect_all 配置参数具有相同的效果。 如果定义了此配置参数,它将覆盖命令行参数。

  • distributed = [Distrib] - 指定哪些应用程序是分布式的,以及允许它们在哪些节点上执行。在此参数中

    • Distrib = {App,Nodes} | {App,Time,Nodes}

    • App = atom()
    • Time = integer()>0
    • Nodes = [node() | {node(),...,node()}]

    该参数在 application:load/2 中进行了描述。

  • dist_auto_connect = Value - 指定何时自动连接节点。如果未指定此参数,则始终自动连接节点,例如,当要向该节点发送消息时。 Value 是以下之一

    • never - 永远不会自动建立连接,必须显式连接。请参阅 net_kernel

    • once - 自动建立连接,但每个节点仅建立一次。如果节点关闭,则必须随后显式连接。 请参阅 net_kernel

  • epmd_module = module() - 配置负责与 epmd 通信的模块。如果未定义此参数,则默认为 erl_epmd

    现在已弃用的命令行参数 -epmd_module <module>epmd_module 配置参数具有相同的效果。如果定义了此配置参数,它将覆盖命令行参数。

  • erl_epmd_node_listen_port = integer() - 配置 erl_epmd 用于侦听连接和连接到其他节点的端口。如果设置了此标志,即使 EPMD 不可用,Erlang VM 也将以分布式模式启动。如果未设置,则会自动选择一个端口(等效于端口 0)。有关更多详细信息,请参阅 erl_epmd

    现在已弃用的命令行参数 erl_epmd_port <module>erl_epmd_node_listen_port 配置参数具有相同的效果。如果定义了此配置参数,它将覆盖命令行参数。

  • permissions = [Perm] - 指定启动应用程序时的默认权限。在此参数中

    • Perm = {ApplName,Bool}
    • ApplName = atom()
    • Bool = boolean()

    application:permit/2 中描述了权限。

  • logger = [Config] - 指定 Logger 的配置,但主要日志级别除外,该级别使用 logger_level 指定,并且与 SASL 错误日志记录的兼容性除外,该兼容性使用 logger_sasl_compatible 指定。

    在 Kernel 用户指南的 日志记录 部分中描述了 logger 参数。

  • logger_level = Level - 指定 Logger 的主要日志级别。具有相同或更严重级别 的日志事件将通过主要日志级别检查。有关 Logger 和日志级别的更多信息,请参阅 Kernel 用户指南中的 日志记录 部分。

    Level = emergency | alert | critical | error | warning | notice | info | debug | all | none

    要在运行时更改主要日志级别,请使用 logger:set_primary_config(level, Level)

    默认为 notice

  • logger_metadata = Metadata - 为日志事件指定主要元数据。

    Metadata = map()

    默认为 #{}

  • logger_sasl_compatible = true | false - 指定 Logger 是否与 Erlang/OTP 21.0 之前的版本的 SASL 错误日志记录功能向后兼容。

    如果此参数设置为 true,则默认的 Logger 处理程序不会记录任何进度、崩溃或监督报告。 如果随后启动了 SASL 应用程序,它会添加一个名为 sasl 的 Logger 处理程序,该处理程序会根据 SASL 配置参数 sasl_error_loggersasl_errlog_type 的值记录这些事件。

    有关 SASL 配置参数的信息,请参阅 sasl(6) 手册页中的 已弃用的错误日志记录事件处理程序和配置 部分。

    有关 SASL 错误日志记录功能以及 Logger 如何与此向后兼容的信息,请参阅 SASL 用户指南中的 SASL 错误日志记录 部分以及 Kernel 用户指南中的 与 error_logger 的向后兼容性 部分。

    默认为 false

    注意

    如果此参数设置为 truesasl_errlog_type 指示应记录进度报告,并且配置的主要日志级别为 notice 或更严重,则 SASL 会自动将主要日志级别设置为 info。也就是说,此设置可能会覆盖内核配置参数 logger_level 的值。这是为了允许将具有日志级别 info 的进度报告转发到处理程序。

  • global_groups = [GroupTuple] - 定义全局组,请参阅 global_group。在此参数中

    • GroupTuple = {GroupName, [Node]} | {GroupName, PublishType, [Node]}

    • GroupName = atom()
    • PublishType = normal | hidden

    • Node = node()
  • inet_default_connect_options = [{Opt, Val}] - 指定 connect 套接字的默认选项,请参阅 inet

  • inet_default_listen_options = [{Opt, Val}] - 指定 listen(和 accept)套接字的默认选项,请参阅 inet

  • inet_dist_use_interface = ip_address() - 如果 Erlang 节点的主机有多个网络接口,则此参数指定要侦听的接口。有关 ip_address() 的类型定义,请参阅 inet

  • inet_dist_listen_min = First
    inet_dist_listen_max = Last

    为分布式 Erlang 节点的侦听器套接字定义 First..Last 端口范围。

  • inet_dist_listen_options = Opts - 定义打开分布式 Erlang 节点的侦听套接字时要使用的额外套接字选项列表。 请参阅 gen_tcp:listen/2

  • inet_dist_connect_options = Opts - 定义一个额外的套接字选项列表,用于连接到其他分布式 Erlang 节点。请参阅 gen_tcp:connect/4

  • inet_parse_error_log = silent - 如果设置此项,当在各种 Inet 配置文件中发现并跳过错误行时,不会发出任何日志事件。

  • inetrc = Filename - Inet 用户配置文件的名称(字符串)。有关详细信息,请参阅 ERTS 用户指南中的 Inet Configuration 部分。

  • net_setuptime = SetupTime - SetupTime 必须为正整数或浮点数,它表示在连接到另一个 Erlang 节点期间,每次网络操作允许的最大时间。最大允许值为 120。如果指定的值更高,则会使用 120。如果未指定该变量或值不正确(例如,不是数字),则默认值为 7 秒。

    请注意,此值不限制总连接建立时间,而是在连接建立和握手期间的每次单独的网络操作的时间。

  • net_ticker_spawn_options = Opts - 为网络定时器进程定义一个额外的 spawn 选项列表。对于与另一个节点的每个连接,都存在一个这样的进程。网络定时器进程负责监督与其关联的连接。这些进程还在建立连接时执行分布握手协议。当存在大量分布连接时,设置垃圾回收选项有助于减少内存使用。默认值为 [link, {priority, max}],并且这两个选项无法更改。monitor{monitor, MonitorOpts} 选项是不允许的,如果存在,将被丢弃。有关有效选项的信息,请参阅 erlang:spawn_opt/4 BIF 的文档。如果 Opts 列表不是一个正确的列表,或者包含无效的选项,则连接的建立将失败。

    请注意,只有当使用的分布载体协议按照 ERTS 用户指南 ➜ 如何为 Erlang 分布实现替代载体 ➜ 分布模块 中描述的方式实现,而没有进一步更改时,上述行为才成立。所使用的分布载体协议的实现者可以选择忽略 net_ticker_spawn_options 参数或更改其行为。但是,目前所有随 OTP 提供的分布模块的行为都如上所述。

  • net_tickintensity = NetTickIntensity - 网络心跳强度 指定在 网络心跳时间 期间,当没有其他数据通过与另一个节点的连接发送时,要发送多少个心跳。这也决定了检查来自另一个节点的数据的频率。网络心跳强度越高,节点检测到无响应节点的时间就越接近所选的网络心跳时间段。网络心跳强度默认为 4NetTickIntensity 的值应为 4..1000 范围内的整数。如果 NetTickIntensity 不是整数或小于 4 的整数,则会静默使用 4。如果 NetTickIntensity 是大于 1000 的整数,则会静默使用 1000

    注意

    请注意,所有通信节点都应使用相同的网络心跳强度以及相同的网络心跳时间

    警告

    请注意不要设置过高的网络心跳强度,因为如果设置得太高,您可能会使节点工作量过大。

  • net_ticktime = NetTickTime - 指定网络心跳时间,以秒为单位。这是连接的节点可能无响应的最长时间,在此之后,它将被视为已关闭并断开连接。

    网络心跳时间和 网络心跳强度 共同决定了一个间隔 TickInterval = NetTickTime/NetTickIntensity。每隔 TickInterval 秒,如果在此前 TickInterval 秒内没有向每个连接的节点发送任何内容,则会向其发送心跳。心跳是在连接上发送的一个小数据包。如果在此前 NetTickIntensityTickInterval 秒间隔内没有收到心跳或有效负载数据包,则连接的节点将被视为已关闭。这确保了由于硬件错误等原因而没有响应的节点被视为已关闭。

    由于仅每 TickInterval 秒检查一次可用性,因此当检测到节点无响应时,节点实际无响应的时间 T 可能在 MinTMaxT 之间变化,其中

    MinT = NetTickTime - NetTickTime / NetTickIntensity
    MaxT = NetTickTime + NetTickTime / NetTickIntensity

    NetTickTime 默认为 60 秒,NetTickIntensity 默认为 4。因此,45 < T < 75 秒。

    注意

    请注意,所有通信节点都必须指定相同NetTickTimeNetTickIntensity 值,因为它决定了发出心跳的频率和预期接收心跳的频率。

    NetTickTime 需要是 NetTickIntensity 的倍数。如果配置的值不是,则 NetTickTime 将在内部向上舍入到最接近的毫秒。但是,net_kernel:get_net_ticktime() 将报告截断为最接近秒的网络心跳时间。

    通常,终止的节点会被传输协议(如 TCP/IP)立即检测到。

  • prevent_overlapping_partitions = true | false - 如果启用 (true),当节点之间的连接丢失时,global 将主动防止形成重叠的分区。此修复程序默认启用。如果您要禁用此修复程序,请务必阅读有关此修复程序的 global 文档,以获取更多重要信息。

  • shutdown_timeout = integer() | infinity - 指定在节点关闭期间 application_controller 等待应用程序终止的时间。如果计时器过期,application_controller 将粗暴地杀死挂起的应用程序的 application_master。如果未定义此参数,则默认为 infinity

  • sync_nodes_mandatory = [NodeName] - 指定此节点要正确启动必须处于活动状态的其他节点。如果列表中的某些节点未在指定的时间内启动,则此节点也不会启动。如果未定义此参数,则默认为 []

  • sync_nodes_optional = [NodeName] - 指定此节点要正确启动可以处于活动状态的其他节点。如果此列表中的某些节点未在指定的时间内启动,则此节点仍会启动。如果未定义此参数,则默认为空列表。

  • sync_nodes_timeout = integer() | infinity - 指定此节点等待强制节点和可选节点启动的时间(以毫秒为单位)。如果未定义此参数,则不执行节点同步。此选项确保 global 同步。

  • start_distribution = true | false - 如果参数为 true,则启动所有分布服务,例如 rpcglobalnet_kernel。对于要禁用所有分布功能的系统,应将此参数设置为 false

    默认为 true

  • start_dist_ac = true | false - 如果参数为 true,则启动 dist_ac 服务器。对于使用分布式应用程序的系统,应将此参数设置为 true

    默认为 false。如果未定义此参数,则当设置参数 distributed 时,将启动服务器。

  • start_boot_server = true | false - 如果参数为 true,则启动 boot_server(请参阅 erl_boot_server)。在使用此服务的嵌入式系统中,应将此参数设置为 true

    默认为 false

  • boot_server_slaves = [SlaveIP] - 如果配置参数 start_boot_servertrue,则可以使用此参数使用从属 IP 地址列表初始化 boot_server

    SlaveIP = string() | atom | {integer(),integer(),integer(),integer()},

    其中 0 <= integer() <=255

    以原子、字符串和元组形式表示的 SlaveIP 示例

    '150.236.16.70', "150,236,16,70", {150,236,16,70}.

    默认为 []

  • start_disk_log = true | false - 如果参数为 true,则启动 disk_log_server(请参阅 disk_log)。在使用此服务的嵌入式系统中,应将此参数设置为 true

    默认为 false

  • start_pg = true | false - 如果参数为 true,则启动默认的 pg 作用域服务器(请参阅 pg)。在使用此服务的嵌入式系统中,应将此参数设置为 true

    默认为 false

  • start_timer = true | false - 如果参数为 true,则启动 timer_server(请参阅 timer)。在使用此服务的嵌入式系统中,应将此参数设置为 true

    默认为 false

  • shell_history = enabled | disabled | module() - 指定是否将 shell 历史记录在 erl 使用之间记录到磁盘 (enabled),完全不记录 (disabled),或者使用用户指定的模块来记录 shell 历史记录。此模块应导出 load() -> [string()],该函数返回一个字符串列表,在 shell 启动时加载,以及 add(iodata()) -> ok.,每次在 shell 中输入新行时调用。默认情况下,日志记录处于禁用状态。

  • shell_history_drop = [string()] - 不应持久化的特定日志行。例如,["q().", "init:stop()."] 将允许忽略关闭节点的命令。默认为 []

  • shell_history_file_bytes = integer() - shell 应记住的字节数。默认情况下,该值设置为 512kb,最小值为 50kb。

  • shell_history_path = string() - 指定 shell 历史记录文件的存储位置。默认为用户缓存目录,由 filename:basedir(user_cache, "erlang-history") 返回。

  • shutdown_func = {Mod :: atom(), Func :: atom()} - 设置一个函数,当 application_controller 开始终止时调用。该函数以 Mod:Func(Reason) 的形式调用,其中 Reasonapplication_controller 的终止原因,并且必须尽快返回,以便 application_controller 正常终止。

  • source_search_rules = [DirRule] | [SuffixRule]

    其中

    • DirRule = {ObjDirSuffix,SrcDirSuffix}
    • SuffixRule = {ObjSuffix,SrcSuffix,[DirRule]}
    • ObjDirSuffix = string()
    • SrcDirSuffix = string()
    • ObjSuffix = string()
    • SrcSuffix = string()

    指定 filelib:find_file/2 filelib:find_source/2 使用的规则列表。如果设置为除空列表之外的其他值,则它将替换默认规则。规则可以是简单的目录后缀对,例如 {"ebin", "src"},由 filelib:find_file/2 使用,或者三元组,指定取决于文件扩展名的单独目录后缀规则,例如 [{".beam", ".erl", [{"ebin", "src"}]},由 filelib:find_source/2 使用。两种规则都可以在列表中混合使用。

    ObjDirSuffixSrcDirSuffix 的解释如下:如果对象所在目录名称的末尾与 ObjDirSuffix 匹配,则通过调用 filelib:wildcard/1 扩展通过将 ObjDirSuffix 替换为 SrcDirSuffix 创建的名称,并且在匹配项中找到的第一个常规文件是源文件。

  • standard_io_encoding = Encoding - 设置通过 standard_io 发送或接收的字节应解释为 unicode 还是 latin1。默认情况下,如果主机支持,则输入和输出将解释为 Unicode。使用此标志,您可以在启动时配置编码。

    这类似于 io:setopts(standard_io, {encoding, Encoding}),但在读取 standard_io 上的任何字节之前应用。

    Encoding 是以下之一

    • unicode - 配置 standard_io 使用 unicode 模式。

    • latin1 - 配置 standard_io 使用 latin1 模式。

    • _ - 除 unicode 或 latin1 之外的任何内容都将被忽略,系统将自行配置编码,通常在现代系统上使用 unicode。

    有关更多详细信息,请参阅 Erlang 中 Unicode 用法中的 Escripts 和非交互式 I/O

  • os_cmd_shell = string() - 指定通过 os:cmd/2 调用系统命令时要使用的 shell。默认情况下,shell 会自动检测。

已弃用的配置参数

在 Erlang/OTP 21.0 中,添加了一个新的日志记录 API。旧的 error_logger 事件管理器和在此管理器上运行的事件处理程序仍然有效,但默认情况下不再使用它们。

仍然可以设置以下应用程序配置参数,但只有在未设置 Logger 的相应配置参数时才使用它们。

  • error_logger - 通过设置默认 logger_std_h 处理程序的 type,以及可能的 filemodes 参数来替换。示例

    erl -kernel logger '[{handler,default,logger_std_h,#{config=>#{file=>"/tmp/erlang.log"}}}]'
  • error_logger_format_depth - 通过设置默认处理程序的格式化程序的 depth 参数来替换。示例

    erl -kernel logger '[{handler,default,logger_std_h,#{formatter=>{logger_formatter,#{legacy_header=>true,template=>[{logger_formatter,header},"\n",msg,"\n"],depth=>10}}}]'

有关更多信息,请参阅 与 error_logger 的向后兼容性