在文章《ST源码分析-st_thread_exit》分析 lookupdns
的时候,当时没有仔细讲解 lookupdns
的退出处理。主要有两个退出处理。
1,do_resolve()
普通协程函数的退出处理。
2,main()
,始祖协程函数的退出处理。
do_resolve()
的流程图如下:
如上图所示,会阻塞在 st_recvfrom()
。最后 return NULL
,但是有一个问题,st_thread_create()
创建协程函数 do_resolve()
的时候,使用了 _st_stack_new()
申请了一块内存,此时此刻 do_resolve()
已经执行完 return NULL
,之前申请的 内存怎么处理?return NULL
之后,代码逻辑会跳到哪里?
首先, do_resolve()
运行的地方是 _st_thread_main()
,如下图:
所以 do_resolve()
的 return NULL
执行完之后,是回到 _st_thread_main()
函数的。就会又执行一次 st_thread_exit()
。
此时,是 第二次执行 st_thread_exit()
,第一次是在 main()
。
回到之前的问题,_st_stack_new()
申请的内存 在何时释放?
解答:在 st_thread_exit()
里面处理,如下图:
从上图可以看到,如果当前协程不是 始祖协程 ,就会调 _st_stack_free()
函数 把内存 放进去全局变量 _st_free_stacks
,下次申请内存就可以直接从 _st_free_stacks
拿。
所以,分析到这里, do_resolve()
的周期就结束了,函数走完了,然后之前申请的内存也放进去内存池里面,_ST_RUNQ
队列也没有了 do_resolve()
。
所以相当于 do_resolve()
协程已经退出了。
接下来分析始祖协程是如何退出的。始祖协程就是 main()
函数,他当时已经执行到了,st_thread_exit(NULL);
,如下图:
始祖协程会不断在 st_thread_exit()
里面 递归
调用 _st_vp_schedule()
进行协程调度,其他协程结束之后,就会停在 idle_thread
里面,看看 _st_idle_thread_start()
函数的代码,如下图:
从上图可以看出,由于已经没有 active 的协程,所以 _st_idle_thread_start()
会直接退出整个程序,至此,始祖协程也就退出了。main() 函数的最后一行代码 return 1;
永远不会执行。
相关阅读:
由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。QQ:2338195090。