现在的位置: 首页 > 综合 > 正文

P2psim 源代码分析(一)

2013年08月19日 ⁄ 综合 ⁄ 共 3573字 ⁄ 字号 评论关闭

P2psim 源代码分析(一)

kejieleung

 

之前暑假本来就开始研究的了,不过后来搞其它项目去,p2psim的研究就放了一段时间了,现在总算能继续看啦哈,很多资料记录了在笔记上,因为放得比较久,现在是一边整理一边再熟悉咯。

网上关系这个仿真的资料真的比较少,而且本身项目在03年之后就没有更新了,不过p2psim的好处是,已经有几个常用的模型的实现,做实验时可以直接拿来分析,再与自己的模型作比较。当然,要能在上面实现自己的模型,还得先明白p2psim的运行机制呀。

慢慢分析啦哈~~~~可能有些不正确的地方,欢迎大家指正、讨论。P2p的配置和架构、类关系可以看我之前发的两篇文章

p2psim学习笔记(一) 編译运行

http://blog.csdn.net/kikikind/archive/2008/08/03/2760576.aspx

p2psim学习笔记(二) 总体框架流程
    http://blog.csdn.net/kikikind/archive/2008/08/04/2765561.aspx

 

 

1.  Main函数Main.c

  1. void
  2. taskmain(int argc, char *argv[])
  3. {
  4.  //kejie:relevant function putenv,setenv,unsetenv  #include<stdlib.h> 
  5.  //get environment variant from name
  6.   p2psim_verbose = getenv("P2PSIM_DEBUG") ? atoi(getenv("P2PSIM_DEBUG")) : 0;
  7.   //kejie:set random seed
  8.   srandom(time(0) ^ (getpid() + (getpid() << 15)));
  9.   parse_args(argc, argv);
  10.   //add in the optional args from parse_args
  11.   //kejie:here just initialize the object
  12.   //<=static Args args() { return _args; } <=  static Args _args; <=class Args : public hash_map<string,string>
  13.   Args a = Node::args ();
  14.  //kejie: in parse_args(-o) ( options.push_back (optarg);)
  15.   for (unsigned int i = 0; i < options.size (); i++) {
  16.    //kejie: split - split a file into pieces( define in parse.c )
  17.     vector<string> x = split (options[i], "=");
  18.     a.insert(make_pair(x[0], x[1]));
  19.   }
  20.   Node::set_args (a);
  21.   // Put a protocol on all these nodes.
  22.   Node::parse(protocol_file);
  23.   //kejie:注册自定义signal
  24.   signal( SIGUSR1, handle_signal_usr1 );
  25.   // Creates a network with the appropriate underlying topology and give Network
  26.   // a chance to eat them all.
  27.   //kejie:在 parse中还会实例化 Network( Network::Instance(top, failure_model); )
  28.   Topology::parse(topology_file);
  29.   
  30.   while(anyready())
  31.     yield();
  32. //kejie:RTT- Round Trip Time 往返时间
  33.   DEBUG(0) << "average RTT = " << Network::Instance()->avglatency()*2 << "ms" << endl;
  34.   // make sure the network ate all the nodes
  35.   while(anyready())
  36.     yield();
  37.   // Creates an event queue, parses the file, etc.
  38.   // Will fire off the EventQueue
  39. //kejie:处理event_file
  40.   EventGenerator::parse(event_file);
  41.   // Initialize all protocols
  42.   if (Node::init_state()) {
  43.     const set<Node*> *all = Network::Instance()->getallnodes();
  44.     for(set<Node*>::const_iterator i = all->begin(); i != all->end(); ++i)
  45.       (*i)->initstate();    //初始化结点,在Node不提供实现,留在具体实现的协议上实现 
  46.   }
  47. }

(1)      

P2p的底层是由libtask实现的模型,不是熟悉的线程,这个taskmain就是作为程序启运后的第一个任务来运行。真正的main函数位置/libtask/task.c

  1. static void
  2. taskmainstart(void *v)
  3. {
  4.     taskmain(taskargc, taskargv);
  5. }
  6. int
  7. main(int argc, char **argv)
  8. {
  9.     argv0 = argv[0];
  10.     taskargc = argc;
  11.     taskargv = argv;
  12.     if(mainstacksize == 0)
  13.         mainstacksize = 256*1024;
  14.     //主任务即在p2psim/main.c
  15.     taskcreate(taskmainstart, nil, mainstacksize);
  16.     taskscheduler();
  17.     fprint(2, "taskscheduler returned in main!/n");
  18.     abort();
  19.     return 0;
  20. }

(2)       先是解释输入参数,再根据参数指定的protocol_file, topology_file, event_file的位置分别读取文件里的所有运行参数。

(3)       这三个文件的处理函数parse()分别作为静态函数封装在NodeTopologyEventGenerator类里

(4)       Task相关的部分定义在/libtask/task.htask.c里,下面是anyready的定义:

  1. int
  2. anyready(void)
  3. {
  4.     return taskrunqueue.head != nil;
  5. }
  6. 任务都放在一个taskrunqueue里,是一个Tasklist的结构,定义如下:
  7. struct Tasklist
  8. {
  9.     Task *head;
  10.     Task *tail;
  11. };

yield 有如下定义:#define yield taskyieldtaskyield为一个函数,调用taskready将当前为taskrunningtask加到taskrunqueue:

  1. int
  2. taskyield(void)
  3. {
  4.     int n;
  5.     
  6.     n = tasknswitch;
  7.     taskready(taskrunning);
  8.     taskswitch();
  9.     return tasknswitch - n;
  10. }
  11. void
  12. taskready(Task *t) 
  13. {
  14.     addtask(&taskrunqueue, t);
  15. }

Taskswitch()

完成相关的运行设置,最后经taskscheduler来调度。不过这部分机制可以不用深入研究,明白怎么运行即可,有兴趣的话可以直接到定义和实现文件里了解整个流程。

(5)       这部分比较容易明白,对照上面的注释即可

 

2.  Main函数用例图说明

 

 

这部分先分析这么多,下一篇重点分板用个处理类NodeTopologyEventGenerator类以及处理的参数文件结构。

 

抱歉!评论已关闭.