注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

freeDiameter源码阅读之 线程模型  

2013-04-02 16:17:45|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

freeDiameterD/
main() ->
fd_core_start

=================
core.c
-------
* Start the server & client threads */
int fd_core_start(void)
{
/* Start server threads */ 启动server 监听线程,监听线程启动 client 对应的peer状态机线程
CHECK_FCT( fd_servers_start() );

/* Start the peer state machines */ 通知所有的peer 线程可以工作了。
CHECK_FCT( fd_psm_start() );

/* Start the core runner thread that handles main events (until shutdown) */ 管理那些关闭信号的吧
CHECK_POSIX( pthread_create(&core_runner, NULL, core_runner_thread, NULL) );

/* Unlock threads waiting into fd_core_waitstartcomplete */
CHECK_FCT( signal_framework_ready() );

/* Ok, everything is running now... */
return 0;
}
==========================

server.c
--------
fd_psm_start
pthread_create serv_th // 检查配置和创建 监听线程
----------
serv_th()
循环等待连接
为新连接创建client_sm 线程
----------
client_sm()
fd_cnx_start_clear // 这里会启动一个接收线程来读取socket内容,并且触发 "新消息"事件
fd_cnx_receive // 等待 第一个CER消息, fd_peer_handle_newCER
fd_peer_handle_newCER // 启动处理线程。
=== ==============

peers.c
-----------
fd_peer_handle_newCER()
fd_psm_begin //启动peer 状态机线程, 等待下面的新连接消息
fd_event_send 发送新的 peer 事件给 PSM (peer state machine 状态机)

================
p_psm.c
---------
fd_psm_begin ()
pthread_create( &peer->p_psm, NULL, p_psm_th, peer ) // 创建状态机线程
--------------
fd_psm_start // daemon 初始化完了应该调用这个通知server的那些peer可以工作了,保证顺序吧。
pthread_cond_broadcast(&started_cnd) //设置条件变量,通知状态机运行
-------------
p_psm_th
fd_psm_waitstart //一直等待状态机的启动条件变量,等待daemon 线程的初始化完成吧?
psm_loop // freeDiameter的事件循环
{
fd_event_timedget(peer->p_events, &peer->p_psm_timer, FDEVP_PSM_TIMEOUT, &event, &ev_sz, &ev_data) // 循环等待下一个事件通知
/* A message was received */
if (event == FDEVP_CNX_MSG_RECV)
fd_msg_parse_buffer
fd_msg_hdr
fd_p_sr_fetch
fd_msg_answ_associate
如果是可路由的消息 {
/* Requeue to the global incoming queue */ 把消息加到队列等待处理???
fd_fifo_post(fd_g_incoming, &msg), goto psm_end );
goto psm_loop; //跳到循环开始
}
其他低层消息
fd_msg_parse_or_error // 检查消息是不是能被内部的 dictionary 识别,不然直接返回错误
fd_out_send
}
================================
conctx.c

/* Connections contexts (cnxctx) in freeDiameter are wrappers around the sockets and TLS operations .
* They are used to hide the details of the processing to the higher layers of the daemon.
* They are always oriented on connections (TCP or SCTP), connectionless modes (UDP or SCTP) are not supported.
*/

/* Lifetime of a cnxctx object:
* 1) Creation
* a) a server socket:
* - create the object with fd_cnx_serv_tcp or fd_cnx_serv_sctp
* - start listening incoming connections: fd_cnx_serv_listen
* - accept new clients with fd_cnx_serv_accept.
* b) a client socket:
* - connect to a remote server with fd_cnx_cli_connect
*
* 2) Initialization
* - if TLS is started first, call fd_cnx_handshake
* - otherwise to receive clear messages, call fd_cnx_start_clear. fd_cnx_handshake can be called later.
*
* 3) Usage
* - fd_cnx_receive, fd_cnx_send : exchange messages on this connection (send is synchronous, receive is not, but blocking).
* - fd_cnx_recv_setaltfifo : when a message is received, the event is sent to an external fifo list. fd_cnx_receive does not work when the alt_fifo is set.
* - fd_cnx_getid : retrieve a descriptive string for the connection (for debug)
* - fd_cnx_getremoteid : identification of the remote peer (IP address or fqdn)
* - fd_cnx_getcred : get the remote peer TLS credentials, after handshake
*
* 4) End
* - fd_cnx_destroy
*/
--------------------------------------

* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */
static void * rcvthr_notls_tcp(void * arg)
循环读取 socket 同时触发 新消息事件
fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV

-----------------------
fd_cnx_start_clear
case IPPROTO_TCP:
/* Start the tcp_notls thread */ 为连接socket 启动接收处理线程。
CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_notls_tcp, conn ) );
---------------------------------


-------------------p_out.c------------------

/* Start the "out" thread that picks messages in p_tosend and send them on p_cnxctx */
int fd_out_start(struct fd_peer * peer)
{
TRACE_ENTRY("%p", peer);
CHECK_PARAMS( CHECK_PEER(peer) && (peer->p_outthr == (pthread_t)NULL) );

CHECK_POSIX( pthread_create(&peer->p_outthr, NULL, out_thr, peer) );

CHECK_FCT( fd_cnx_unordered_delivery(peer->p_cnxctx, 1) );

return 0;
}




---------routing_dispatch.c-------------

消息路由部分,还有3个全部peer共用的消息路由处理线程。

所有的发送接收的消息,应该都是先经过这个统一处理,再分发给不同的peer的独立的线程进一步处理。


/* The dispatch thread */
static void * dispatch_thr(void * arg)
{
return process_thr(arg, msg_dispatch, fd_g_local, "Dispatch");
}

/* The (routing-in) thread -- see description in freeDiameter.h */
static void * routing_in_thr(void * arg)
{
return process_thr(arg, msg_rt_in, fd_g_incoming, "Routing-IN");
}

/* The (routing-out) thread -- see description in freeDiameter.h */
static void * routing_out_thr(void * arg)
{
return process_thr(arg, msg_rt_out, fd_g_outgoing, "Routing-OUT");
}

总结:
可以看到 freeDiameter为每个peer创建1个是peer的状态机线程循环处理各种事件和状态转换,一个是专门负责读取socket消息的线程,这个读到消息之后会触发事件通知第一线程处理。另外还有专门的发送socket网络数据的xi线程,另外还有可能有处理消息超时的线程。
这个不是多个peer的连接共享一个事件处理线程的模型。 因为diameter只需要peer和peer之间使用一个连接就可以了,总的peer的数量或者说连接数量是比较少的。这个模型应该是可以满足要求的。
另外这个连接对应的 peer的状态机事件循环处理线程,只是简单的把消息又通过队列转发给message routing dispatch 做线程去处理的。 message dispatch线程在程序启动时创建,根据配置启动一个或者多个处理线程。在那里才对消息进行详细的解析,然后调用 扩展插件之类的。所用的连接共用一个或者多个message dispatch消息处理线程。
  评论这张
 
阅读(725)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017