2012-12-10 13 views
1

Erlang的进程将调用link/1spawn_link与另一个进程创建链接。在我最近的一个应用程序中,我很好奇它是否有可能让某个进程知道给定的实例,以及与其链接的其他进程的数量。这可能吗 ?他们是BIF吗?“我有多少个链接?”,询问Erlang进程

然后,当链接进程死亡时,我猜如果有可能知道链接进程的数量,那么这个数字会被运行时系统自动减少。这种机制对于处理Erlang并发程序中的Parent-Child关系是理想的,即使在简单的关系中也不涉及supervisors

那么,Erlang进程是否有可能通过BIF(链接到它的进程数)知道,这样每当链接进程死亡时,该值就会自动减少under-the-hood :)?


在这个问题上扩大一点点,考虑gen_server,这将通过handle_info处理数以千计的邮件。在这部分,它的工作是dispatch子进程处理任务,一旦它进来。其目的是为了确保server loop立即返回以接受下一个请求。现在,子进程异步处理任务,并在应用程序死亡之前将回复发回给请求者。在继续之前,请参阅此question及其答案。

现在,如果为gen_server产生的每个子进程创建一个链接,并且我希望将此链接用作计数器。我知道,我知道,每个人都会像“为什么不使用gen_server State,携带说,一个计数器,然后相应地增加或减少它?”:)在gen_server的某处,我有:

handle_info({Sender,Task},State)-> 
    spawn_link(?MODULE,child,[Sender,Task]), 
    %% At this point, the number of links to the gen_server is incremented 
    %% by the run-time system 
    {noreply,State}; 
handle_info(_ ,State) -> {noreply,State}. 

的孩子去上做到这一点:

child(Sender,Task)-> 
    Result = (catch execute_task(Task)), 
    Sender ! Result, 
    ok. %% At this point the child process exits, 
     %% and i expect the link value to be decremented 

然后最后,gen_server有这样一个公开的调用:

get_no_of_links()-> gen_server:call(?MODULE,links). 
handle_call(links, _ ,State)-> 
    %% BIF to get number of instantaneous links expected here 
    Links = erlang:get_links(), %% This is fake, do not do it at home :) 
    {reply,Links,State}; 
handle_call(_ , _ ,State)-> {reply,ok,State}. 

现在,有人可能会问他们的自我,真的,为什么会任何人想要这样做?

通常情况下,它可能在gen_server状态中创建一个整数,然后我们自己做,或者至少使gen_server handle_info类型为{'EXIT',ChildPid,_Reason},然后服务器将相应地执行。我的想法是,如果有可能知道链接的数量,我会用它来了解(在特定的时间点),有多少子进程仍在忙于工作,这反过来可能实际上有助于预测服务器负载。

+1

为什么不使用gen_server国家,携带说,一个计数器,然后递增或递减相应的呢? – r3m0t

+0

我想你错过了这个问题。我谈到了这一点。谢谢 –

+1

你没有说你为什么不想这样做。 – r3m0t

回答

6

从手册process_info:

{链接,PIDS}: PIDS是PID的一个列表,与进程到 具有链路

3> process_info(self(), links). 
{links,[<0.26.0>]} 
4> spawn_link(fun() -> timer:sleep(100000) end). 
<0.38.0> 
5> process_info(self(), links).     
{links,[<0.26.0>,<0.38.0>]} 

我想的过程它可以被用来计算链接进程数

+0

这是件好事。除了问题是,如果进程数量很大,查询链接的数量需要执行可能消耗内存的“length/1”,如果进程列表处于数千? –

+0

那么,你可以尝试在所需的过程中设置trace [procs],并手动捕获所有'link'/'unlink'/'getting_linked'事件并增加计数器。但我不确定这会如何影响整体表现 – 2012-12-10 14:21:29

2

你的过程应该运行process_flag(trap_exit, true)和听对于形式为{'EXIT', Pid, Reason}的消息,只要链接的进程退出就会到达。如果您不捕获退出,则当链接的另一端退出时,链接进程的默认行为将会退出。

至于监听进程何时添加链接,您可以使用case process_info(self(), links) of {links, L} -> length(L) endlength(element(2, process_info(self(), links)),但是您必须定期重新运行它,因为每当添加链接时都无法通知您的进程。

以下OTP指南的过程永远不会需要知道多少进程被链接到它。