nng协议nni_posix_resolv_sysinit()系统初始化

avatar
作者
猴君
阅读量:4

        nni_posix_resolv_sysinit(void) 实现了一个初始化函数 nni_posix_resolv_sysinit,用于设置解析系统(resolver system)。它主要负责初始化解析线程池,用于并发处理域名解析请求。

源码:

int nni_posix_resolv_sysinit(void) { 	resolv_fini = false; 	nni_aio_list_init(&resolv_aios);  #ifndef NNG_RESOLV_CONCURRENCY #define NNG_RESOLV_CONCURRENCY 4 #endif  	resolv_num_thr = (int) nni_init_get_param( 	    NNG_INIT_NUM_RESOLVER_THREADS, NNG_RESOLV_CONCURRENCY); 	if (resolv_num_thr < 1) { 		resolv_num_thr = 1; 	} 	// no limit on the maximum for now 	nni_init_set_effective(NNG_INIT_NUM_RESOLVER_THREADS, resolv_num_thr); 	resolv_thrs = NNI_ALLOC_STRUCTS(resolv_thrs, resolv_num_thr); 	if (resolv_thrs == NULL) { 		return (NNG_ENOMEM); 	}  	for (int i = 0; i < resolv_num_thr; i++) { 		int rv = nni_thr_init(&resolv_thrs[i], resolv_worker, NULL); 		if (rv != 0) { 			nni_posix_resolv_sysfini(); 			return (rv); 		} 	} 	for (int i = 0; i < resolv_num_thr; i++) { 		nni_thr_run(&resolv_thrs[i]); 	}  	return (0); }  

过程分析:

1. 对全局变量resolv_aios初始化:

   这里首先贴一下resolv_aios 的类型:

//nni_list_node 的类型定义: typedef struct nni_list_node { 	struct nni_list_node *ln_next; 	struct nni_list_node *ln_prev; } nni_list_node;  //nni_list 的类型定义: typedef struct nni_list { 	struct nni_list_node ll_head; 	size_t               ll_offset; } nni_list;  //resolv_aios 的定义 static nni_list resolv_aios;

        基本流程:首先初始化全局变量 resolv_fini = false;  紧接着初始化了全局变量  resolv_aios  

这里简单插一句初始化的过程:nni_aio_list_init(&resolv_aios);

void nni_aio_list_init(nni_list *list) { 	NNI_LIST_INIT(list, nni_aio, a_prov_node); }  #define NNI_LIST_INIT(list, type, field) \ 	nni_list_init_offset(list, offsetof(type, field))   void nni_list_init_offset(nni_list *list, size_t offset) { 	list->ll_offset       = offset; 	list->ll_head.ln_next = &list->ll_head; 	list->ll_head.ln_prev = &list->ll_head; } 

简单分析一下就是,nni_aio_list_init()函数对全局变量 resolv_aios  的初始化操作。而nni_aio_list_init  的定义是一个宏:NNI_LIST_INIT,这个是通用的宏定义,其他初始化也会用到。在这个宏里,传入了3个参数:

第一个就是我们的全局变量的地址:&resolv_aios

第二个是 type类型,这里是  nni_aio 这个结构体

第三个是 a_prov_node

在宏里调用了函数 nni_list_init_offset (list,  offsetof(type,  field))这里的type就是 nni_aiofield是 a_prov_node offsetof是一个内核中常用的宏,用于计算结构体类型距离结构体首地址的偏移量。我们可以在代码中加一行计算这个值并输出:offserof aio -> a_prov_node=[408]。甚至我们可以通过内存对齐算一下这个值。

//在文件/src/platform/posix/posix_resolv_gai.c的480行添加下面的代码 printf("offserof aio -> a_prov_node=[%d]\n", offsetof(nni_aio, a_prov_node)); //我们将看到输出是 offserof aio -> a_prov_node=[408]

初始化之后的值为:

resolv_aios->ll_ofset  = 408; resolv_aios->ll_head.ln_next = &resolv_aios->ll_head; resolv_aios->ll_head.ln_prev = &resolv_aios->ll_head;

当然我们也可以直接在初始化完成后进行直接输出,经过验证:resolv_aios.ll_offset=[408];其实就是对全局变量 resolv_aios 的指针及 ll_offset 字段进行了初始化。结果如上。

  • resolv_fini 被设置为 false,表示解析系统还未完成。
  • nni_aio_list_init 函数初始化一个异步I/O列表 resolv_aios,用于存储待处理的解析请求。

2. 解析并发级别设置

  • 如果未定义 NNG_RESOLV_CONCURRENCY,则将其定义为 4。
  • 使用 nni_init_get_param 获取解析线程数,默认值为 NNG_RESOLV_CONCURRENCY
  • 确保解析线程数至少为 1。 

这里不做详细分析,感兴趣的同学请分析并留下链接,大家一起学习。

3. 分配解析线程结构数组

        分配  resolv_thrs 数组,大小为 resolv_num_thr ;

        分配失败则返回内存不足

4. 初始化和启动解析线程

        这里对 resolv_aios逐个(这里是4个,执行同样的操作)进行初始化。调用的函数是不是有点眼熟!nni_thr_init 。

这里的参数类型是 nni_thr (和前面一篇 nni_posix_global_pollq 初始化的成员变量是同一类型)。为方便查看,这里再次贴出nni_thr的类型定义:

struct nni_thr { 	nni_plat_thr thr; 	nni_plat_mtx mtx; 	nni_plat_cv  cv; 	nni_thr_func fn; 	void *       arg; 	int          start; 	int          stop; 	int          done; 	int          init; };  //上面结构体的成员变量 struct nni_plat_thr { 	pthread_t tid; 	void (*func)(void *); 	void *arg; }; 

在 nni_thr_init  函数中,对每个resolv_thrs[i] 数组元素进行一次初始化操作,初始化之后的值是:

&resolv_thrs[i]->done  = 0; &resolv_thrs[i]->start = 0; &resolv_thrs[i]->stop  = 0; &resolv_thrs[i]->fn    = resolv_worker; &resolv_thrs[i]->arg   = NULL;  

同样,对thr->thr 也会进行初始化,执行函数nni_plat_thr_init (&thr->thr, nni_thr_wrap, thr  );

初始化后的值是:

nni_thr的成员变量 nni_plat_thr nni_thr->nni_plat_thr->func = nni_thr_wrap; nni_thr->nni_plat_thr->arg  = nni_thr; 

接下来创建一个线程, 线程的id 就是 nni_thr->nni_plat_thr->tid,线程属性沿用了前面初始化的线程属性。 执行线程函数 nni_plat_thr_main。在线程函数中,会执行函数

nni_thr->func(nni_thr->arg);这里就执行nni_thr初始化的函数 resolv_worker,回顾上面的初始化过程可知,参数是NULL。

这段代码通过设置并发解析线程池来初始化解析系统,用于处理异步域名解析请求。初始化过程中包括全局变量和AIO列表的初始化、解析并发级别的设置、解析线程结构数组的分配以及解析线程的初始化和启动。整个过程确保解析系统能够高效地并发处理解析请求。

5. resolv_worker的执行(待续。。。)

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!