lib/kernel/src/gen_tcp.erl
send(S, Packet) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> Mod:send(S, Packet); Error -> Error end.
lib/kernel/src/inet_tcp.erl
%% %% Send data on a socket %% send(Socket, Packet, Opts) -> prim_inet:send(Socket, Packet, Opts). send(Socket, Packet) -> prim_inet:send(Socket, Packet, []).
erts/preloaded/src/prim_inet.erl
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% SEND(insock(), Data) -> ok | {error, Reason} %% %% send Data on the socket (io-list) %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This is a generic "port_command" interface used by TCP, UDP, SCTP, depending %% on the driver it is mapped to, and the "Data". It actually sends out data,-- %% NOT delegating this task to any back-end. For SCTP, this function MUST NOT %% be called directly -- use "sendmsg" instead: %% send(S, Data, OptList) when is_port(S), is_list(OptList) -> ?DBG_FORMAT("prim_inet:send(~p, ~p)~n", [S,Data]), try erlang:port_command(S, Data, OptList) of false -> % Port busy and nosuspend option passed ?DBG_FORMAT("prim_inet:send() -> {error,busy}~n", []), {error,busy}; true -> receive {inet_reply,S,Status} -> ?DBG_FORMAT("prim_inet:send() -> ~p~n", [Status]), Status end catch error:_Error -> ?DBG_FORMAT("prim_inet:send() -> {error,einval}~n", []), {error,einval} end.
看到了使用erlang:port_command/3来向ERTS发送数据,根据erlang:port_command的文档的说明,
引用
port_command(Port, Data, OptionList) -> boolean()
Types:
Port = port() | atom()
Data = iodata()
Option = force | nosuspend
OptionList = [Option]
Sends data to a port. port_command(Port, Data, [])
equals port_command(Port, Data).
If the port command is aborted false is returned; oth-
erwise, true is returned.
If the port is busy, the calling process will be sus-
pended until the port is not busy anymore.
Currently the following Options are valid:
force:
The calling process will not be suspended if the
port is busy; instead, the port command is forced
through. The call will fail with a notsup exception
if the driver of the port does not support this.
For more information see the ERL_DRV_FLAG_SOFT_BUSY
driver flag.
nosuspend:
The calling process will not be suspended if the
port is busy; instead, the port command is aborted
and false is returned.
我们知道OptionList可以是force和nosuspend,当设置该选项时,如果port处于busy状态,该调用进程不会被挂起,而是会强制执行,如果这个端口的驱动不支持该行为的话,调用程序将收到一个notsup的异常;当nosuspend选项被设置时,如果port处于busy状态,调用进程不会被挂起,而是收到false的返回。
而在erlang:system_monitor/2中,
引用
erlang:system_monitor(MonitorPid, Options) -> MonSettings
Types:
MonitorPid = pid()
Options = [system_monitor_option()]
MonSettings = undefined | {OldMonitorPid, OldOp-
tions}
OldMonitorPid = pid()
OldOptions = [system_monitor_option()]
system_monitor_option() = busy_port
| busy_dist_port
| {long_gc, integer() >= 0}
| {long_schedule, integer() >= 0}
| {large_heap, integer() >= 0}
.....
busy_port:
If a process in the system gets suspended because
it sends to a busy port, a message {monitor, Sus-
Pid, busy_port, Port} is sent to MonitorPid. SusPid
is the pid that got suspended when sending to Port.
如果设置了busy_port选项时,当被monitor的进程因为调用的port处于busy状态而被挂起时,monitor进程会收到{monitor, SusPid, busy_port, Port}消息,SusPid是被监控的进程ID