tread master机制(转载)

  • 格式:pdf
  • 大小:153.67 KB
  • 文档页数:25

zebra的Thread机制zebra的Thread机制1.thread的四种创建方法一个新的thread可以通过如下三种方式被创建,主要是看你需要创建的thread的类型:1,thread_add_read:添加一个thread到readqueue,该thread负责通过socket接受和读取从client端来的数据。

2,thread_add_write:添加一个thread到writequeue,该thread负责通过socket向client端填充和写数据。

3,thread_add_timerfunctioncalls:添加一个thread到timerqueue,该thread负责定时一个event,例如update和redistribute一个routetable.

4,thread_add_event:添加一个eventthread到eventqueue。上面这三个函数的处理过程都差不多:1,创建thread。首先在unusequeue查找,如果有unusethread,就使用它,否则重新分配空间。

2,根据参数,对thread进行赋值。3,将该thread加入到相应的queue中。2.thread的调用1,bgpdaemon不断地从eventqueue中取出thread并且执行它。一旦该thread被执行了,将该thread的type设置为unuse。并且将该thread添加到unusequeue中。

2,如果eventqueue为空时,bgpdaemon通过select函数监控读、写、异常三个描述符集。一旦有某个描述符准备就绪,则将该描述符所对应的thread加入readyqueue.

而对于timerqueue中的thread,只有当select函数超时后才会进入readyqueue.3.zebrad端的threadzebrad启动后会,在readqueue中会出现两个thread,一个是等待来自localclient端bgpd的连接,另一个是等待来自vtyclient端的连接。

第1个threadzebra_init()->zebra_serv_un()中创建一个thread,加入readqueue。该thread的处理函数为zebra_accept,监听内部client的socket。

zebra_client_create(client_sock);创建一个新的zebraclient/*Registermyself.*/zebra_event(ZEBRA_SERV,accept_sock,NULL);继续监听serversocketputs("<-zebra_accept");return0;}

vty_accept,加入readqueue。作为vtyserver监听internet的vtysocket.。vty_create(vty_sock,&su);根据vty_sock和ip地址信息su,创建一个新的vty。

puts("<-vty_accept");return0;}

vty_flush。vty_event(VTY_READ,vty_sock,vty);根据newclientvty的vty_sock创建新的VTY_READthread,加入readqueue,该thread的处理函数为vty_read。

returnvty;}

sockunion_bind(accept_sock,&su,port,NULL);将accept_socket文件描述符与一个特定的逻辑网络连系起来。服务器端使用su->sin.sin_addr.s_addr=htonl(INADDR_ANY);表示接受任何一个主机网络接口上的连接请求。

if(ret<0){close(accept_sock);/*Avoidsdleak.*/return;}/*Listensocketunderqueue3.*/ret=listen(accept_sock,3);将accept_sock套接口设置成被动监听状态,用于接受连接,只能在服务器端使用。if(ret<0){zlog(NULL,LOG_WARNING,"can'tlistensocket");close(accept_sock);/*Avoidsdleak.*/return;}

/*Addvtyserverevent.*/vty_event(VTY_SERV,accept_sock,NULL);}

sockunion_bind操作/*Bindsockettospecifiedaddress.*/intsockunion_bind(intsock,unionsockunion*su,unsignedshortport,unionsockunion*su_addr){intsize=0;intret;

if(su->sa.sa_family==AF_INET){size=sizeof(structsockaddr_in);su->sin.sin_port=htons(port);#ifdefHAVE_SIN_LENsu->sin.sin_len=size;#endif/*HAVE_SIN_LEN*/if(su_addr==NULL)su->sin.sin_addr.s_addr=htonl(INADDR_ANY);服务器一般将sin_addr.s_addr字段设置为INADDR_ANY表示套接字应接收任何一个主机网络接口上的连接请求。

客户端将sin_addr.s_addr字段设置为服务器主机的IP地址。}#ifdefHAVE_IPV6elseif(su->sa.sa_family==AF_INET6){size=sizeof(structsockaddr_in6);su->sin6.sin6_port=htons(port);#ifdefSIN6_LENsu->sin6.sin6_len=size;#endif/*SIN6_LEN*/if(su_addr==NULL){#ifdefined(LINUX_IPV6)||defined(NRL)bzero(&su->sin6.sin6_addr,sizeof(structin6_addr));#elsesu->sin6.sin6_addr=in6addr_any;#endif/*LINUX_IPV6*/}}#endif/*HAVE_IPV6*/ret=bind(sock,(structsockaddr*)su,size);if(ret<0)zlog(NULL,LOG_WARNING,"can'tbindsocket:%s",strerror(errno));

returnret;}

vty_event操作/*structthread_master*master;*/staticvoidvty_event(enumeventevent,intsock,structvty*vty){structthread*vty_serv_thread;switch(event){caseVTY_SERV:vty_serv_thread=thread_add_read(master,vty_accept,vty,sock);vector_set_index(Vvty_serv_thread,sock,vty_serv_thread);break;caseVTY_READ:vty->t_read=thread_add_read(master,vty_read,vty,sock);/*Timeouttreatment.*/if(vty->v_timeout){if(vty->t_timeout)thread_cancel(vty->t_timeout);vty->t_timeout=thread_add_timer(master,vty_timeout,vty,vty->v_timeout);}break;caseVTY_WRITE:if(!vty->t_write)vty->t_write=thread_add_write(master,vty_flush,vty,sock);break;caseVTY_TIMEOUT_RESET:if(vty->t_timeout){thread_cancel(vty->t_timeout);vty->t_timeout=NULL;}if(vty->v_timeout){vty->t_timeout=thread_add_timer(master,vty_timeout,vty,vty->v_timeout);}break;}}

第2个threadbgp_serv_sock()->bgp_serv_sock_family()中创建一个thread,不是通过event的方式添加的。该thread的处理函数为bgp_accept。作为bgp_server,接受来自internet上的bgp连接。

bgp_serv_sock_family操作port=179family=AF_INET/*Makebgpd'sserversocket.*/voidbgp_serv_sock_family(unsignedshortport,intfamily){intret;