erlang:port_command函数

今天读到[url=blog.yufeng.info]褚霸[/url]博客里的[url=blog.yufeng.info/archives/336]gen_tcp:send的深度解刨和使用指南(初稿)[/url]时,顺着霸爷的思路,跟着
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的文档的说明,
[quote]
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.
[/quote]
我们知道OptionList可以是force和nosuspend,当设置该选项时,如果port处于busy状态,该调用进程不会被挂起,而是会强制执行,如果这个端口的驱动不支持该行为的话,调用程序将收到一个notsup的异常;当nosuspend选项被设置时,如果port处于busy状态,调用进程不会被挂起,而是收到false的返回。

而在erlang:system_monitor/2中,
[quote]
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.
[/quote]
如果设置了busy_port选项时,当被monitor的进程因为调用的port处于busy状态而被挂起时,monitor进程会收到{monitor, SusPid, busy_port, Port}消息,SusPid是被监控的进程ID
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值