游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

skynet源码阅读系列03skynetcontextnew

  上一节看了skynetstart()的一部分代码,那部分代码主要做了下面几件事。如果当前进程收到SIGHUP信号,则调用handlehup函数,将SIG设为1检查配置文件内的deamon配置,这个配置对应一个文件路径,文件内的记录进程的pid号,防止重复启动skynet进程,第一次启动将自动将进程号写入文件。重定向了文件描述符,把文件描述符0,1,2重定向到了devnull,相当于当前进程忽略了标准输入,标准输出,标准错误。初始化了HARBOR的值,HARBOR的值为配置文件内harbor配置的值左移24位。初始化了一个handlestorage结构体,结构体内包含一个harbor成员,其中限定了harbor最高为0xff,也就是(28)1,所以harbor的取值在1255之间,之后再左移24位,和HARBOR保持一致。初始化了一个全局消息队列,全局消息队列里的每一个元素都是一个子消息队列,其中子消息队列的元素内包含具体的消息。初始化了一个modules结构体M,结构体内包含一个path成员,保存着配置文件内的cpath配置,一个skynetmodule类型的数组m,数组长度为32。初始化了定时器模块,暂时不细节功能实现,但是我们知道模块里定时器的时间单位是1100秒。初始化了socket模块,暂时不细节,不影响我们捋顺框架。把配置文件的profile配置保存在GNODE中。
  以上就是skynetstart()前半段代码做的一些事了。
  今天的内容主要梳理了一下skynetcontextnew这个函数都做了什么。
  接着skynetstart()的内容看:structskynetcontextctxskynetcontextnew(configlogservice,configlogger);if(ctxNULL){fprintf(stderr,Cantlaunchsservice,configlogservice);exit(1);}
  可以看到,这段代码无非是尝试去创建一个skynetcontext结构体。
  如果创建失败了,整个进程就退出了。
  下面我们看看skynetcontextnew()函数。structskynetcontextskynetcontextnew(constcharname,constcharparam){structskynetmodulemodskynetmodulequery(name);if(modNULL)returnNULL;voidinstskynetmoduleinstancecreate(mod);if(instNULL)returnNULL;structskynetcontextctxskynetmalloc(sizeof(ctx));CHECKCALLINGINIT(ctx)ctxmodmod;ctxinstanceinst;ATOMINIT(ctxref,2);ctxcbNULL;ctxcbudNULL;ctxsessionid0;ATOMINIT(ctxlogfile,(uintptrt)NULL);ctxinitfalse;ctxendlessfalse;ctxcpucost0;ctxcpustart0;ctxmessagecount0;ctxprofileGNODE。profile;Shouldsetto0firsttoavoidskynethandleretireallgetanuninitializedhandlectxhandle0;ctxhandleskynethandleregister(ctx);structmessagequeuequeuectxqueueskynetmqcreate(ctxhandle);initfunctionmaybeusectxhandle,soitmustinitatlastcontextinc();CHECKCALLINGBEGIN(ctx)intrskynetmoduleinstanceinit(mod,inst,ctx,param);CHECKCALLINGEND(ctx)if(r0){structskynetcontextretskynetcontextrelease(ctx);if(ret){ctxinittrue;}skynetglobalmqpush(queue);if(ret){skyneterror(ret,LAUNCHss,name,param?param:);}returnret;}else{skyneterror(ctx,FAILEDlaunchs,name);uint32thandlectxhandle;skynetcontextrelease(ctx);skynethandleretire(handle);structdroptd{handle};skynetmqrelease(queue,dropmessage,d);returnNULL;}}
  好长
  不急,我们一点点看。structskynetmodulemodskynetmodulequery(name);if(modNULL)returnNULL;
  查询name表示的模块,如果没查到,就returnNULLstructskynetmoduleskynetmodulequery(constcharname){structskynetmoduleresultquery(name);if(result)returnresult;SPINLOCK(M)resultquery(name);doublecheckif(resultNULLMcountMAXMODULETYPE){intindexMcount;voiddltryopen(M,name);if(dl){Mm〔index〕。namename;Mm〔index〕。moduledl;if(opensym(Mm〔index〕)0){Mm〔index〕。nameskynetstrdup(name);Mcount;resultMm〔index〕;}}}SPINUNLOCK(M)returnresult;}
  skynetmodulequery:调用query()查找,查到了直接返回。staticstructskynetmodulequery(constcharname){inti;for(i0;iMcount;i){if(strcmp(Mm〔i〕。name,name)0){returnMm〔i〕;}}returnNULL;}
  从之前初始化好的modulesM结构体内的数组中查找,如果在数组内返回。
  如果不在数组内,skynetmodulequery()将尝试打开name文件。staticvoidtryopen(structmodulesm,constcharname){constcharl;constcharpathmpath;sizetpathsizestrlen(path);sizetnamesizestrlen(name);intszpathsizenamesize;searchpathvoiddlNULL;chartmp〔sz〕;do{memset(tmp,0,sz);while(path;)path;if(path)break;lstrchr(path,;);if(lNULL)lpathstrlen(path);intlenlpath;inti;for(i0;path〔i〕!?ilen;i){tmp〔i〕path〔i〕;}memcpy(tmpi,name,namesize);if(path〔i〕?){strncpy(tmpinamesize,pathi1,leni1);}else{fprintf(stderr,InvalidCservicepath);exit(1);}dldlopen(tmp,RTLDNOWRTLDGLOBAL);pathl;}while(dlNULL);if(dlNULL){fprintf(stderr,tryopensfailed:s,name,dlerror());}returndl;}
  我们可以看到tryopen()函数一直从path(对应配置文件的cpath)中的路径进行尝试,并将?替换为name,也就是传入的文件名,尝试打开文件,如果dl不为NULL,则说明找到了该文件,跳出循环之后还没找到则不在cpath里。
  不能理解上面的话可以看这里:
  一般我们在配置文件配填cpath的配置是这样的root。cpathroot。。cservice?。so;。。root。。xxx?。so
  这段config的lua代码会在main函数内被执行一次,所以cpath的值将变成。cservice?。so;。xxx?。so,假如我们的namelog
  tryopen()就是把cpath里的?替换成log,再以;为分隔符分割,得到。cservicelog。so,。xxxlog。so。
  然后再传入dlopen(),尝试打开动态链接库。intindexMcount;voiddltryopen(M,name);if(dl){Mm〔index〕。namename;Mm〔index〕。moduledl;if(opensym(Mm〔index〕)0){Mm〔index〕。nameskynetstrdup(name);Mcount;resultMm〔index〕;}}
  我们再回到skynetmodulequery(),正常打开之后把相关的信息保存在modulesM,Mm,skynetmodule类型的数组里。structskynetmodule{constcharname;voidmodule;skynetdlcreatecreate;skynetdlinitinit;skynetdlreleaserelease;skynetdlsignalsignal;};name:文件名module:dlopen打开的链接库句柄create:name文件内的{s}create,name函数指针。init:name文件内的{s}init,name函数指针。release:name文件内的{s}release,name函数指针。signal:name文件内的{s}signal,name函数指针。
  所以我们写C服务时应包含create,init,release,signal四个函数,这四个函数的函数名应加上文件名作为前缀。
  小结一下就是skynetmodulequery()函数会从M中查找对应的skynetmodule结构体对象,如果找到了直接返回,没找到就从配置文件里cpath路径找对应的文件,如果找到了加载到内存中,并保存到M里,下次就不用重复打开了,返回对象。
  画了个简单的图可以参考下:
  下面我们继续回到skynetcontextnew()里。voidinstskynetmoduleinstancecreate(mod);if(instNULL)returnNULL;voidskynetmoduleinstancecreate(structskynetmodulem){if(mcreate){returnmcreate();}else{return(void)(intptrt)(0);}}
  返回这个c模块里相应的create函数返回值,否则返回(void)(intptrt)(0)。structskynetcontextctxskynetmalloc(sizeof(ctx));CHECKCALLINGINIT(ctx)structskynetcontext{voidinstance;structskynetmodulemod;voidcbud;skynetcbcb;structmessagequeuequeue;ATOMPOINTERlogfile;uint64tcpucost;inmicrosecuint64tcpustart;inmicroseccharresult〔32〕;uint32thandle;intsessionid;ATOMINTref;intmessagecount;boolinit;boolendless;boolprofile;CHECKCALLINGDECL};defineCHECKCALLINGINIT(ctx)
  创建了一个skynetcontext结构体ctx。ctxmodmod;ctxinstanceinst;ATOMINIT(ctxref,2);ctxcbNULL;ctxcbudNULL;ctxsessionid0;ATOMINIT(ctxlogfile,(uintptrt)NULL);ctxinitfalse;ctxendlessfalse;ctxcpucost0;ctxcpustart0;ctxmessagecount0;ctxprofileGNODE。profile;
  初始化了一些信息。Shouldsetto0firsttoavoidskynethandleretireallgetanuninitializedhandlectxhandle0;ctxhandleskynethandleregister(ctx);uint32tskynethandleregister(structskynetcontextctx){structhandlestoragesH;rwlockwlock(slock);for(;;){inti;uint32thandleshandleindex;for(i0;isslotsize;i,handle){if(handleHANDLEMASK){0isreservedhandle1;}inthashhandle(sslotsize1);if(sslot〔hash〕NULL){sslot〔hash〕ctx;shandleindexhandle1;rwlockwunlock(slock);handlesharbor;returnhandle;}}assert((sslotsize21)HANDLEMASK);structskynetcontextnewslotskynetmalloc(sslotsize2sizeof(structskynetcontext));memset(newslot,0,sslotsize2sizeof(structskynetcontext));for(i0;isslotsize;i){inthashskynetcontexthandle(sslot〔i〕)(sslotsize21);assert(newslot〔hash〕NULL);newslot〔hash〕sslot〔i〕;}skynetfree(sslot);sslotnewslot;sslotsize2;}}
  之前在skynethandle。c中声明过一个handlestorageH,其中包括harbor,现在用到了其中的handleindex,slotsize,slot;
  slot的类型为skynetcontext,ctx为skynetcontext,之前为slot申请了slotsize个skynetcontext大小的内存,所以slot内可以放slotsize个指针。
  skynethandleregister()实现了以下功能,从slot中找到一个位置存ctx,其中位置0是保留的,如果找到了,直接返回,则下次找的时候从当前位置的下一个位置找,handleindex存的是下次开始找的位置。
  如果没找到,则申请别原来多一倍的空间啊,再把所有的元素重新hash,重新保存到newslot里,释放原来的空间,最外层for循环再执行一次,这次肯定就能有位置放了。
  其实通过handle就可以找到ctx的下标了,hashhandle(sslotsize1)handlesharbor;returnhandle;
  最后返回handle,注意这里的structmessagequeuequeuectxqueueskynetmqcreate(ctxhandle);initfunctionmaybeusectxhandle,soitmustinitatlastcontextinc();structmessagequeueskynetmqcreate(uint32thandle){structmessagequeueqskynetmalloc(sizeof(q));qhandlehandle;qcapDEFAULTQUEUESIZE;qhead0;qtail0;SPININIT(q)Whenthequeueiscreate(alwaysbetweenservicecreateandserviceinit),setinglobalflagtoavoidpushittoglobalqueue。Iftheserviceinitsuccess,skynetcontextnewwillcallskynetmqpushtopushittoglobalqueue。qinglobalMQINGLOBAL;qrelease0;qoverload0;qoverloadthresholdMQOVERLOAD;qqueueskynetmalloc(sizeof(structskynetmessage)qcap);qnextNULL;returnq;}
  创建一个消息队列,初始化handle:处理这个消息的handlecap:消息队列的capcity容量head,tail:头尾指针inglobal:是否在全局消息队列里release:是否析构了overload:是否过载overloadthreshold:过载阈值queue:当前消息队列中消息指针next:全局消息队列中下一个消息队列的指针contextinc();staticvoidcontextinc(){ATOMFINC(GNODE。total);}
  初始化GNODE。total,原子类型。CHECKCALLINGBEGIN(ctx)intrskynetmoduleinstanceinit(mod,inst,ctx,param);CHECKCALLINGEND(ctx)intskynetmoduleinstanceinit(structskynetmodulem,voidinst,structskynetcontextctx,constcharparm){returnminit(inst,ctx,parm);}
  这里调用c模块的init函数,这里的话也就是loggerinit。intloggerinit(structloggerinst,structskynetcontextctx,constcharparm){constcharrskynetcommand(ctx,STARTTIME,NULL);inststarttimestrtoul(r,NULL,10);if(parm){insthandlefopen(parm,a);if(insthandleNULL){return1;}instfilenameskynetmalloc(strlen(parm)1);strcpy(instfilename,parm);instclose1;}else{insthandlestdout;}if(insthandle){skynetcallback(ctx,inst,loggercb);return0;}return1;}
  我们可以看到,如果parm存在,也就是configlogger存在,对应配置文件的logger字段,如果存在,则追加输出到文件内,否则输出到stdout。if(r0){structskynetcontextretskynetcontextrelease(ctx);if(ret){ctxinittrue;}skynetglobalmqpush(queue);if(ret){skyneterror(ret,LAUNCHss,name,param?param:);}returnret;}else{skyneterror(ctx,FAILEDlaunchs,name);uint32thandlectxhandle;skynetcontextrelease(ctx);skynethandleretire(handle);structdroptd{handle};skynetmqrelease(queue,dropmessage,d);returnNULL;}
  如果初始化成功,则将消息队列push到全局消息队列,否则进行析构操作。

华为云WeLink免费提供视频会议,减少面对面交流感谢IT之家网友怂的线索投递!IT之家1月26日消息根据华为的官方消息,1月25日至6月1日期间,将为用户免费提供视频会议。华为表示,在疫情期间,为减少人与人的面对……平面图形的拼组教学反思《平面图形的拼组》是在学生已经认识了平面图形长方形、正方形、三角形和圆的基础上,通过动手拼组,进一步认识平面图形的一些特征及图形之间的一些关系。这是一节操作性很强的课,主要是让……联想集团首批IT设备抵达武汉市火神山医院,进入调试阶段联想集团日前通过官方微信及官方微博宣布,集团已经紧急启动驰援武汉行动。联想集团将向武汉市火神山医院捐赠全套IT设备,以加快医院落成。截至28日,前两批IT设备已经紧急调运,首批……网易云音乐推出音街App,对标阿里唱鸭腾讯全民K歌IT之家3月13日消息据Tech星球报道,网易云音乐近日推出一款名为音街的产品,这是网易云音乐首次入局免费K歌市场,并推出独立App。音街目前需要邀请码才能进入,登录界面……没开玩笑!B站将上线指环王霍比特人全系列电影后天能看IT之家4月1日消息B站即将上线《指环王》《霍比特人》全系列6部电影,电影将于4月3日下午6点可以观看。IT之家此前曾报道字节系应用春节期间请用户免费观看《囧妈》,赚得一……太阳是大家的优秀教案设计学习目标1。认识彤、陪2个生字,会写彤、霞、陪、趁4个生字,正确读写红彤彤、晚霞、浪花、睡觉、睡梦等词语。2。正确、流利、有感情地朗读课文。背诵课文。3。懂得……课文荷的教案设计一、《荷》专题1、欣赏荷花的美,了解荷的有关知识。2、学习咏荷诗文,培养学生的语言感知能力、想象能力、欣赏能力和对其文化的领悟能力。3、培养收集信息、整理信息……互联网档案馆宣布暂时开放140万册版权书籍借阅IT之家3月30日消息据外媒报道,互联网档案馆(InternetArchive)日前宣布,鉴于疫情,暂时开放140万册版权图书的借阅,直至6月30日或美国国家紧急状态结束,以较……自然教案设计之水的三态变化一、教学目的1使学生知道霜是水蒸气遇到0以下的物体结成的冰晶;水有三种状态,在一定条件下是可以相互变化的。(能有条理地复述,会画图说明。)2培养学生的实验能力(学习……谷歌首页涂鸦上新,建议人们待在家中感谢IT之家网友仿达的线索投递!IT之家4月5日消息据IT之家网友投稿,日前谷歌搜索首页更换了新的涂鸦,建议人们待在家里。新涂鸦中,Google几个字母分别被分配到……年轻力壮的造句1、即便是在西方社会,我们对性研究的焦点也仅限于城市地区,年轻力壮的人群,白人群。2、健康储蓄账户是为纳税人建立的,我还年轻力壮,很乐意多工作。3、王说,我过去总以……微信发起知识星光公益计划使用微信支付可为乡村小学捐书IT之家1月2日消息根据微信官方的消息,新年伊始,微信与腾讯公益慈善基金会共同发起知识星光公益计划,打开微信完成支付后,搜索知识星光,点击进入集满99颗星光就可以为乡村小学的孩……
男子不服违停处罚拍抖音辱骂交警被行政拘留15天IT之家1月4日消息无论是辱骂警察等公职人员还是辱骂他人,都是违法行为,侵犯了他人的人格尊严和名誉权。人格尊严权和名誉权是公民的基本人身权利。《宪法》第38条规定:中华人民共和……九年级英语下册Moudle910总复习资料(外研版)九年级下册moudle910一、重点词汇:i根据首字母及句意提示写出下列单词。1。w(无论何处)yougointheworld,iwillwaitforyou……大海是什么颜色优秀教学设计范文教学目标:1、能用自己的方法认识9个生字,并能工整、正确地书写8个字,感受汉字的形体美。2、能正确、流利、有感情地朗读课文,进一步练习朗读疑问语气的句子,结合图文理……文旅部试行旅游市场黑名单将老赖纳入管理,联合惩戒IT之家12月29日消息据文化和旅游部网站发布,为维护旅游市场秩序,加快旅游领域信用体系建设,促进旅游业高质量发展,近日,文化和旅游部印发《旅游市场黑名单管理办法(试行)》。《……海南新建住宅须100配建充电基础设施据海南省近期出台的《海南省电动汽车充电基础设施建设运营暂行管理办法》规定,新建居住类建筑要按照配建停车位的100建设或预留充电条件。根据办法,居住类建筑按照配建停车位的1……第五章环节动物门P教学目标1了解蚯蚓的生活习性和适于穴居生活的形态、结构、生理等方面的特征;了解蚯蚓与人类的关系,在了解其它环节动物的基础上,理解环节动物门的主要特征。2通过……程序员偷走单位CPU,警方动用无人机搜山IT之家9月5日消息据现代快报报道,近日苏州高新区某公司12台电脑的CPU被盗,总价值近两万元,警察调查后发现嫌疑男子正是该公司的程序开发员潘某。报道称,通过查阅现场监控……说课大班科学课堂教案前一阶段,我班的孩子一直在玩沉与浮的游戏。他们从日常生活中找来了各种物品放入水中进行实验,如:木珠、海棉、回形针、木片、塑料积木等等。观察其在水中沉浮的情况并做好记录。孩子们不……江苏高考新政出台在即采取312模式,总分升到750IT之家3月12日消息据新浪教育的新闻,江苏高考新政出台在即,江苏省常熟中学高一年级选科动员大会视频在网上流传,而视频中老师介绍,新高考选科采用了312模式,江苏高考的总分将变……CNN航空分析师波音737MAX8可能被全球停飞IT之家3月11日消息昨日,埃塞俄比亚航空公司一架波音737客机从埃塞俄比亚首都亚的斯亚贝巴飞往肯尼亚首都内罗毕途中遭遇事故,致飞机坠毁,机上157人遇难。CNN航空分析师表示……学习3以内的数数教案设计目标:1、在操作活动中学习3以内的数数。2、学习单位量词,了解数的实际意义。3、激发学习兴趣,培养观察能力。准备:小猪洗澡的图片,15圆点卡片和数字卡片……生活中的推理教学设计教学内容:生活中的推理教学目标:1、能对生活中的某些现象按一定的方法进行逻辑推理、判断其结果。2、在解决问题的过程中,学习一些简单的推理方法。通过经历观……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网