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
。