bind udp 数据处理
简介本文简要介绍一下BIND9中的UDP数据处理,包括bind是如何处理UDP报文,如何收发报文信息,创建socket设置什么socket参数、多线程环境中如何让多个线程读取53端口的数据。对于UDP而言,BIND9的做法是在主进程中创建好UDP socket,然后各个线程都在这个fd上通过recvmsg来收取消息并处理。 函数调用关系ns_interface_listenudp <–ns_interface_setup <– do_scan <– ns_interfacemgr_scan0 <– ns_interfacemgr_scan <– scan_interfaces <–load_configuration <– run_server <– ns_server_create <– setup <– main setup到load_configuration load_configuratin 到ns_interfacemgr_scan0 ns_interface_scan0 到ns_interface_listernudp ok到此处已经开启监听udp 请求。下面看看他是如何实现的 这张图主要关注do-scan到dns_dispatch_getudp 紧接着调用get_udpsocket()创建新的socket对象,get_udpsocket()中关键的是open_socket函数,它创建一个socket,并调用bind绑定IP地址和端口。关键步骤是: dns_dispatch_getudp到get_udpsocket 创建socket 通过dns_dispatch_getudp之后,就调用 1.client->sendevent处 理client_senddone; 详细的函数关系调用 对于UDP,client_start调用执行client_udprecv()函数,client_udprecv的核心是执行isc_socket_recv2函数,isc_socket_recv2的核心是执行socket_recv();socket_recv的核心是doio_recv(),doio_recv()中就是recvmsg()系统调用。 工作线程上面的isc_task_send(client->task,&ev);被调用后主要的工作就交给了 工作线程去处理了。具体流程如下。 从上图中可以看到,当线程通过recvmsg接收到数据后会交给队列中的线程执行client_request()函数;client_request就是解包处理DNS请求。 如果线程通过recvmsg没有接收到数据,则将这个fd加入到epoll的监听队列中(BIND9有一个单独的线程执行epoll循环),当这个fd上有读事件的时候,epoll线程会调用internal_recv()处理UDP数据,internal_recv的核心依然是doio_recv函数。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |