社区新版论坛已上线,点击立即前往!使用 openKylin 账户授权登录,解锁更多体验!

openKylin论坛

 找回密码

ms()用途浅析 [复制链接]

erlang系统的application,稍微复杂一点的都会提供一个ms/0的导出函数,而且这个导出函数通常在文档里面找不到描述,很奇怪不是吗?
比如mnesia就有这样的ms, 我们来看下:
$ erlErlang R17A (erts-5.11) [source-b7fbc28] [64-bit] [smp:16:16] [async-threads:10] [hipe] [kernel-poll:false]Eshell V5.11  (abort with ^G)1> mnesia:ms().[mnesia,mnesia_backup,mnesia_bup,mnesia_checkpoint, mnesia_checkpoint_sup,mnesia_controller,mnesia_dumper, mnesia_loader,mnesia_frag,mnesia_frag_hash, mnesia_frag_old_hash,mnesia_index,mnesia_kernel_sup, mnesia_late_loader,mnesia_lib,mnesia_log,mnesia_registry, mnesia_schema,mnesia_snmp_hook,mnesia_snmp_sup, mnesia_subscr,mnesia_sup,mnesia_text,mnesia_tm, mnesia_recover,mnesia_locker,mnesia_monitor,mnesia_event]2> 看起来貌似只是返回组成mnesia的模块列表而已。
那么它的作用是什么呢?
复杂一点的程序都需要在运行期间来进行观察或者优化,比如说dbg跟踪一个函数或者模块运作的时候,是需要这个模块的名字的,如:
dbg:tp(Module,MatchSpec)
那么如果要跟踪整个application的运作,我们通常会写这样的代码:
[do_some_thing(M) || M所以这就是ms的意义所在。
现在的问题是mnesia的代码是把ms的模块硬编码的,这样会带来一个维护的问题,比如添加,改名或者减少一个模块都要记得去修改这个列表,很麻烦。
%mnesia.erlms() ->    [     mnesia,     mnesia_backup,     mnesia_bup,...].程序员是个很懒的群体,必定不会这么挫的,于是rebar就专门花了点力气把这个事情做的漂亮。
rebar在编译application的时候,会把src/myapp.app.src的内容添加以下内容:
{modules,[mod_a, mod_b,...]}
形成ebin//myapp.app文件,这个文件是每个app必须的!
rebar处理这个事情的核心代码如下:
%%rebar_otp_app.erlAppVars = load_app_vars(Config1) ++ [{modules, ebin_modules()}],ebin_modules() ->    lists:sort([rebar_utils:beam_to_mod("ebin", N) ||                   N <- rebar_utils:beams("ebin")]).
简单的演示下效果:
$ cat *.src{application,ump_proxy,             [{description,"ump proxy"},              {vsn,"2.3.4"},              {registered,[]},              {applications,[kernel,stdlib,sasl,observer,runtime_tools,os_mon, tools, webtool,appmon,              ump_log,ump_zk,ump_mq]},              {mod,{ump_proxy_app,[]}}]}.$ cat ../ebin/*.app{application,ump_proxy,             [{description,"ump proxy"},              {vsn,"2.3.4"},              {registered,[]},              {applications,[kernel,stdlib,sasl,observer,runtime_tools,os_mon,                             tools,webtool,appmon,ump_log,ump_zk,ump_mq]},              {mod,{ump_proxy_app,[]}},              {modules,[test_ump_proxy_partitioner,ump_mysql_protocol,                        ump_proxy_app,ump_proxy_backend,ump_proxy_connection,                        ump_proxy_connection_manager,ump_proxy_connection_sup,                        ump_proxy_global,ump_proxy_global_lib,                        ump_proxy_handle,ump_proxy_keepalive_sup,ump_proxy_ms,                        ump_proxy_partition_fsm,ump_proxy_partitioner,                        ump_proxy_partitioner_nifs,ump_proxy_qps_manager,                        ump_proxy_qps_user,ump_proxy_qps_user_sup,                        ump_proxy_rpc,ump_proxy_rw_split_fsm,                        ump_proxy_safe_counter,ump_proxy_safe_counter_server,                        ump_proxy_service_stats,ump_proxy_session,                        ump_proxy_session_manager,ump_proxy_session_sup,                        ump_proxy_socket,ump_proxy_ssl,ump_proxy_stats,                        ump_proxy_sup,ump_proxy_timer,ump_proxy_util]}]}.所以有了rebar的帮忙后,这个事情就很简单了。
我们可以这样写:
ms() -> {ok, Mods} = application:get_key(modules), Mods.
顺手再展示下ms()的用途:
get_old_code_process_num(AppName) ->   Processes = [Pid || Pid <- processes(),              application:get_application(Pid) =:= {ok, AppName}],   {ok, Mods} = application:get_key(AppName, modules),   OldNum = length([Pid || Pid <- Processes, is_using_old_code(Pid, Mods)]),   TotalNum = length(Processes),   case TotalNum of        0 -> {0, 0, 0};        _ ->           Ratio  =  round(OldNum / TotalNum * 10000),           {OldNum, TotalNum, Ratio}   end.is_using_old_code(_, []) -> false;is_using_old_code(Pid, [H|T]) ->   erlang:check_process_code(Pid, H) orelse is_using_old_code(Pid, T).小结: erlang是个考虑非常到位和成熟的系统。
祝玩得开心!


原创文章,转载请注明:转载自系统技术非业余研究


楼主
发表于 2013-8-9 12:32:58
回复

使用道具 举报

openKylin

GMT+8, 2024-6-24 21:00 , Processed in 0.069806 second(s), 18 queries , Gzip On.

Copyright ©2022 openKylin. All Rights Reserved .

ICP No. 15002470-12 Tianjin

快速回复 返回顶部 返回列表