unbound入口在run_daemon方法。
daemon_init方法,分配struct daemon结构体,设置信号处理方法,初始化openssl库,设置时区,设置daemon->need_to_exit为0,初始化模块栈(modstack_init方法)设置deamon->mods结构体(struct module_stack)的num为0、mod为NULL,为daemon->env(struct module_env*)分配内存,把&daemon->mod设置到daemon->env->modstack上,初始化edns选项(edns_known_options_list方法)设置daemon->env的edns_known_options_num值为0、edns_known_options指针分配256个sizeof(struct edns_known_option)大小的内存,初始化daemon->superalloc结构体(struct alloc_cache),为daemon
->acl(struct acl_list *)、daemon->acl_interface(struct acl_list )、daemon->tcl(struct tcl_list )指针分配内存,调用listen_setup_locks方法初始化stream_wait_count_lock、http2_query_buffer_count_lock、http2_response_buffer_count_lock锁,设置启动时间daemon->time_boot、daemon->time_boot_last(struct timeval)为当前时间,为daemon->env->auth_zones(struct auth_zones)分配内存(内部是一颗红黑树,根据class和zone比较:auth_zone_cmp、auth_xfer_cmp),为daemon->env->ends_strings(struct edns_strings)分配内存。
config_create方法,为cfg变量(struct config_file)分配内存,根据方法中cfgfile(char)参数和daemon->chroot变量读取配置文件到cfg中。
apply_setting方法,把cfg设置到daemon->cfg上,设置日志可见性verbosity全局变量,根据配置文件设置一些全局变量,设置文件数量和内存大小限制(rlimit),设置日志ident(默认是unbound),分别创建以下缓存:
- daemon->env->msg_cache (struct slabhash *)第一层哈希表大小为
cfg->msg_cache_slabs
、二层哈希表大小为1024,最大内存为cfg->msg_cache_size
,比较方法为query_info_compare(比较type、class、域名),key:struct msgreply_entry
,data:struct reply_info
。 - daemon->env->rrset_cache(struct rrset_cache*)内部也是struct slabhash结构,第一层哈希表大小为
cfg->rrset_cache_slabs
(默认是4)、二层哈希表大小为1024,最大内存为cfg->rrset_cache_size
(默认为4M),比较方法为ub_rrset_compare(比较type、class、域名),key:struct ub_packed_rrset_key
,data:struct packed_rrset_data
。 - daemon->env->infra_cache(struct infra_cache*):内部有3个slabhash,分别是cfg->env->infra_cache->hosts、cfg->env->infra_cache->domain_rates、cfg->env->infra_cache->client_ip_rates,1颗红黑树cfg->env->infra_cache->domain_limits、2颗地址树cfg->env->infra_cache->wait_limits_netblock、cfg->env->infra_cache->wait_limits_cookie_netblock。
- hosts:struct slabhash结构,第一层哈希表大小为
cfg->infra_cache_slabs
、二层哈希表大小为32,最大内存为cfg->infra_cache_numhosts * (sizeof(struct infra_key)+sizeof(struct infra_data)+ 14)
,比较方法为infra_compfunc(比较sock地址、zone),key:struct infra_key
,data:struct infra_data
。- domain_rates:struct slabhash结构,第一层哈希表大小为
cfg->ratelimit_slabs
、二层哈希表大小为32,最大内存为cfg->ratelimit_size
,比较方法为rate_compfunc(比较域名),key:struct rate_key
,data:struct rate_data
。- client_ip_rates:struct slabhash结构,第一层哈希表大小为
cfg->ip_ratelimit_slabs
、二层哈希表大小为32,最大内存为cfg->ip_ratelimit_size
,比较方法为ip_rate_compfunc(比较ip地址),key:struct ip_rate_key
,data:struct ip_rate_data
(也是struct rate_data
)。- domain_limits:struct rbtree_type结构,节点为
struct domain_limit_data
,比较方法为name_tree_compare(比较class、域名),存储从配置文件中读取的cfg->ratelimit_for_domain、cfg->ratelimit_below_domain的域名限制。
slabhash是一个二级哈希表,第二级哈希表是lru哈希表。
config_lookup_uid方法,获取uid和gid。
daemon_open_shared_ports方法,根据cfg->ifs获取网卡地址或者ip地址和端口,如果开启reuseport选项且线程数量大于1就开启reuseport,把创建好的监听套接字设置到daemon->ports上,如果cfg->remote_control_enable为1,创用于远程控制的套接字daemon->rc_ports。
perform_setup方法,设置远程控制的ssl相关的东西,设置syslog,创建pid文件干掉旧进程,设置了daemon模式则fork子进程挂到后台,切换当前工作目录、uid、gid,设置日志文件。
daemon_fork方法
- 通过views_create方法,创建daemon->views(
struct views *
)红黑树,节点为struct view *
,比较方法为view_cmp(比较域名)。 - 通过views_apply_cfg方法,把daemon->cfg->views中的配置添加到daemon->views方法。
- 通过acl_list_apply_cfg方法,创建daemon->acl(
struct acl_list *
)红黑树,节点为struct addr_tree_node
,比较方法为addr_tree_cmp(比较网段),并读取配置中的acl配置加载到daemon->acl中,并添加127.0.0.0/8 allow
和::1 allow
、::ffff:127.0.0.1 allow
规则。 - 通过acl_interface_apply_cfg方法,创建daemon->acl_interface(
struct acl_list *
)红黑树,节点为struct acl_addr
。