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

skynet源码阅读系列04skynetstart收尾

  上一小节主要是梳理了一下skynetcontextnew()的功能。
  skynetcontextnew()主要功能是创建一个skynetcontext。
  根据传入的name从配置的cpath路径对应的。so库中查找。
  我们写的C服务需要包含四个函数,假如name为logger,则这四个函数的函数名分别为loggercreateloggerreleaseloggerinitloggersignal
  skynetcontext结构体包含以下成员:structskynetcontext{voidinstance;创建出的服务实例structskynetmodulemod;内存里该C服务句柄voidcbud;skynetcbcb;structmessagequeuequeue;该服务的消息队列ATOMPOINTERlogfile;uint64tcpucost;inmicrosecuint64tcpustart;inmicroseccharresult〔32〕;暂存结果uint32thandle;启动该服务后,服务号intsessionid;ATOMINTref;intmessagecount;boolinit;init之后为falseboolendless;boolprofile;配置文件profile的值CHECKCALLINGDECL};
  上述成员变量没注释的从main看到这里,暂时不清楚是做什么的,往后继续阅读就清楚了。
  今天我们接着skynetstart()继续看,完整的函数体在下面。voidskynetstart(structskynetconfigconfig){registerSIGHUPforlogfilereopenstructsigactionsa;sa。sahandlerhandlehup;sa。saflagsSARESTART;sigfillset(sa。samask);sigaction(SIGHUP,sa,NULL);if(configdaemon){if(daemoninit(configdaemon)){exit(1);}}skynetharborinit(configharbor);skynethandleinit(configharbor);skynetmqinit();skynetmoduleinit(configmodulepath);skynettimerinit();skynetsocketinit();skynetprofileenable(configprofile);structskynetcontextctxskynetcontextnew(configlogservice,configlogger);if(ctxNULL){fprintf(stderr,Cantlaunchsservice,configlogservice);exit(1);}skynethandlenamehandle(skynetcontexthandle(ctx),logger);bootstrap(ctx,configbootstrap);start(configthread);harborexitmaycallsocketsend,soitshouldexitbeforesocketfreeskynetharborexit();skynetsocketfree();if(configdaemon){daemonexit(configdaemon);}}
  只剩下下面这点没看了。skynetstart(structskynetconfigconfig){。。。skynethandlenamehandle(skynetcontexthandle(ctx),logger);bootstrap(ctx,configbootstrap);start(configthread);harborexitmaycallsocketsend,soitshouldexitbeforesocketfreeskynetharborexit();skynetsocketfree();if(configdaemon){daemonexit(configdaemon);}}
  skynethandlenamehandle(skynetcontexthandle(ctx),logger);constcharskynethandlenamehandle(uint32thandle,constcharname){rwlockwlock(Hlock);constcharretinsertname(H,name,handle);rwlockwunlock(Hlock);returnret;}
  我们可以看到,skynethandlenamehandle()的功能是insertname()。
  看看insertname()的具体实现:staticconstcharinsertname(structhandlestorages,constcharname,uint32thandle){intbegin0;intendsnamecount1;while(beginend){intmid(beginend)2;structhandlenamensname〔mid〕;intcstrcmp(nname,name);if(c0){returnNULL;}if(c0){beginmid1;}else{endmid1;}}charresultskynetstrdup(name);insertnamebefore(s,result,handle,begin);returnresult;}
  很明显的一个二分查找,判断传入的name是否在Hname里,这是一个指针,指向一块内存,其内存元素的类型为skynetname,定义如下:structhandlename{charname;uint32thandle;};structhandlestorage{。。。intnamecap;name指向内存块的容量intnamecount;name指向内存块当前已经占用了几个元素,每个元素为一个skynetnamestructhandlenamename;指向一块内存};
  为什么这里可以使用二分查找?
  我们看下strcmp()函数的功能
  百度百科:strcmp函数是stringcompare(字符串比较)的缩写,用于比较两个字符串并根据比较结果返回整数。基本形式为strcmp(str1,str2),若str1str2,则返回零;若str1str2,则返回负数;若str1str2,则返回正数。
  我们可以依据返回的结果判断,如果为0说明找到了,直接返回,后面的逻辑就不跑了,如果0,说明结果在mid的右边,beginmid1,反之endmid1。
  既然可以使用了二分查找,那一定要保证数组的有序咯?
  我们接着往下看,
  charresultskynetstrdup(name);将name拷贝了一份,为什么要拷贝,下面解释。
  insertnamebefore(s,result,handle,begin);函数原型如下:staticvoidinsertnamebefore(structhandlestorages,charname,uint32thandle,intbefore){if(snamecountsnamecap){snamecap2;assert(snamecapMAXSLOTSIZE);structhandlenamenskynetmalloc(snamecapsizeof(structhandlename));inti;for(i0;ibefore;i){n〔i〕sname〔i〕;}for(ibefore;isnamecount;i){n〔i1〕sname〔i〕;}skynetfree(sname);snamen;}else{inti;for(isnamecount;ibefore;i){sname〔i〕sname〔i1〕;}}sname〔before〕。namename;sname〔before〕。handlehandle;snamecount;}
  首先我们看else分支,此时Hname指向的内存还没放满元素,将从before下标开始到之后一个元素,将数组统一向后挪一个位置,不过都是从末端开始,到before截至。
  before也就是传入函数的begin,是name将要插入的位置,将下标比begin大的元素往后移,将name插入begin的位置,从而保证了数组的有序。
  如果if(snamecountsnamecap)如果容量不够了,将容量扩充至原来的两倍,并且有一个MAXSLOTSIZE最大值内存上限,将before之前的元素重新写入内存,之后的元素向后挪一个位置,同时释放掉原内存空间,中间before的位置写入name。
  注意这里的释放操作,也就是为什么insertname()里为什么要拷贝一份的原因了。
  接下来是bootstrap(ctx,configbootstrap);staticvoidbootstrap(structskynetcontextlogger,constcharcmdline){intszstrlen(cmdline);charname〔sz1〕;charargs〔sz1〕;intargpos;sscanf(cmdline,s,name);argposstrlen(name);if(argpossz){while(cmdline〔argpos〕){argpos;}strncpy(args,cmdlineargpos,sz);}else{args〔0〕;}structskynetcontextctxskynetcontextnew(name,args);if(ctxNULL){skyneterror(NULL,Bootstraperror:s,cmdline);skynetcontextdispatchall(logger);exit(1);}}
  我们拿exampleconfig下的配置举例,config下的bootstrap配置如下。bootstrapsnluabootstrapTheserviceforbootstrap
  bootstrap()函数体内在调用skynetcontextnew()之前,主要是把snlua赋值给name,而空格之后的字符串即为args的值。
  然后再把name,args传入skynetcontextnew()函数,从snlua。so中查找模块并创建实例。
  如果失败了,把消息队列里的消息分发完,退出。
  start(configthread);staticvoidstart(intthread){pthreadtpid〔thread3〕;structmonitormskynetmalloc(sizeof(m));memset(m,0,sizeof(m));mcountthread;msleep0;mmskynetmalloc(threadsizeof(structskynetmonitor));inti;for(i0;ithread;i){mm〔i〕skynetmonitornew();}if(pthreadmutexinit(mmutex,NULL)){fprintf(stderr,Initmutexerror);exit(1);}if(pthreadcondinit(mcond,NULL)){fprintf(stderr,Initconderror);exit(1);}createthread(pid〔0〕,threadmonitor,m);createthread(pid〔1〕,threadtimer,m);createthread(pid〔2〕,threadsocket,m);staticintweight〔〕{1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,};structworkerparmwp〔thread〕;for(i0;ithread;i){wp〔i〕。mm;wp〔i〕。idi;if(isizeof(weight)sizeof(weight〔0〕)){wp〔i〕。weightweight〔i〕;}else{wp〔i〕。weight0;}createthread(pid〔i3〕,threadworker,wp〔i〕);}for(i0;ithread3;i){pthreadjoin(pid〔i〕,NULL);}freemonitor(m);}
  声明了一个线程数组,数组大小为configthread3。structmonitor{intcount;structskynetmonitorm;pthreadcondtcond;pthreadmutextmutex;intsleep;intquit;};
  创建了一个monitor结构体,初始化数据count:configthreadsleep:0m:为每个thread创建了一个skynetmonitorcond:条件变量mutex:互斥锁createthread(pid〔0〕,threadmonitor,m);createthread(pid〔1〕,threadtimer,m);createthread(pid〔2〕,threadsocket,m);
  创建了三个线程,monitor,timer,socket,这就是声明数组大小为thread3的原因。
  createthread()的函数原型如下:staticvoidcreatethread(pthreadtthread,void(startroutine)(void),voidarg){if(pthreadcreate(thread,NULL,startroutine,arg)){fprintf(stderr,Createthreadfailed);exit(1);}}
  参数thread:指向线程的指针startroutine:指向函数的指针arg:void指针
  创建线程,并指明线程运行函数的起始地址,也就是我们传入的函数指针指向的地址,arg将最为参数传递给startroutine函数。staticintweight〔〕{1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,};structworkerparmwp〔thread〕;for(i0;ithread;i){wp〔i〕。mm;wp〔i〕。idi;if(isizeof(weight)sizeof(weight〔0〕)){wp〔i〕。weightweight〔i〕;}else{wp〔i〕。weight0;}createthread(pid〔i3〕,threadworker,wp〔i〕);}for(i0;ithread3;i){pthreadjoin(pid〔i〕,NULL);}freemonitor(m);
  创建剩下的thread个线程,并且传入workerparm结构体作为参数,结构体包含structworkerparm{structmonitorm;指向skynetmonitor类型的指针intid;intweight;权重,后面有用};
  最后,join,free。
  start()的功能就是为整个框架创建好线程,线程数量由config文件的thread参数配置,还包括框架本身需要的3个线程,monitor,timer,socket。
  继续回到skynetstart()函数。harborexitmaycallsocketsend,soitshouldexitbeforesocketfreeskynetharborexit();skynetsocketfree();if(configdaemon){daemonexit(configdaemon);}
  最后join调线程之后再把harbor,socket,等相关资源释放掉。
  skynetstart()到这里就结束了,是不是很奇怪,是不是感觉还有很多事情没有做(如果有skynet使用经验会有这种感觉),别急,后面我们继续看。

名企头条阿里巴巴回应被罚182亿外媒称腾讯收购搜狗获批准阿里巴巴回应处罚决定:我们诚恳接受,坚决服从自2015年以来,阿里巴巴集团对平台内商家提出二选一要求,禁止平台内商家在其他竞争性平台开店或参加促销活动,如此行为已涉嫌构成……车载摄像头真有这么香?特斯拉前脚释出大额订单日本光学巨头也官《科创板日报》(编辑郑远方),自动驾驶车载摄像头领域又迎来一位巨头。佳能近日宣布,已与TierIV公司签署战略合作备忘录,生产销售车载摄像头,用于自动驾驶、ADAS(先进驾驶辅……各位老铁推荐一款用2年不太卡的国产手机,现在用的荣耀9X?感谢您的阅读!实际上,现在的国产手机使用23年基本上都不会出现卡顿的情况。我们今天就和大家一起了解一下目前大家使用的一些手机,特别是国产手机的情况。我们就好比题主正……WhatsApp功能上线,潜客电话等你来拿前有Facebook、后有LinkedIn,再有Instagram,那么,社媒获客怎么能少得了WhatsApp呢?或许你会疑惑,相比Facebook、LinkedIn、Inst……白话大数据一、什么是大数据?1、专家学者眼里的大数据:第一种说法:需具备5V特征:Volume(大量)、Velocity(高速)、Variety(多样)、Value(低……声色俱佳,JBLT280TWSPLUS试用首先感谢Zaaap!和JBL提供的这次T280TWSPLUS耳塞的众测试用机会。Zaaap!非常贴心的给耳塞做了精美的包装,还附赠了一张祝福卡片,好评!!!JBL的……对于一个打算做自媒体的新人来讲,最起码需要购买哪些设备?很多人虽然在头条看了很多内容,却没有真正做过自媒体,不知道自媒体创作需要用到什么设备,家里没有电脑可以做自媒体吗?这里我就来告诉大家,做自媒体需要用到的设备,贵不贵呢?下面就来……设计模式14观察者模式观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。什么……让这些ROG电竞外设陪你十一开黑50v50大型攻城团战?看看这款MMO新生代大作!玩家国度ROG前天点击蓝字关注我们如果经常关注游戏圈的小伙伴们可能会发现近期一款新游频频登上Steam……华为手机如何做到大屏追剧,小屏聊天?只需打开这个功能!本文来自花粉俱乐部眸小汐曦华为手机中的手机无线投屏、电脑模式的操作,如大屏看片,小屏聊天、一机两用,隐私保护,一键甩屏等操作,相信大家都有着浓厚的体验兴趣,很多人都想拿出……亚马逊代运营的工作内容有哪些?经常会有人问我:你们做亚马逊代运营,都做哪些工作,为什么要收这么多钱?我这个人特别不喜欢被别人质疑,所以我一般只回答我们会做哪些工作。看完了我们做亚马逊代运营的工作内容,如果你……Lexar推出256GBUHSIIV90记忆卡产品闪存解决方案厂商雷克沙近日宣布推出256GB容量的Professional2000xSDXCUHSII卡GOLD系列,读取速度最高可达300MBs,是专为单反相机和电影级摄像机……
车站气三方联动实现氢燃料汽车的高效运营随着国家政策的驱动,国内氢燃料汽车已由星星之火逐步发展为燎原之势。加氢站作为氢燃料汽车氢气供应的重要保障,是支撑氢燃料汽车产业发展必不可少的基石。氢能产业的基础环节在于制氢、储……卧室多出来的面积,到底该不该做卫生间?针对一些空间面积比较大的卧室,往往会将床和梳妆台以外多出来的面积开拓出新的领域。比如给卧室增加一个卫生间,减轻空间负担,增加使用者的便利,缩短每次起夜需要活动的距离。……华为畅连能否取代微信?这个问题很有意思,作为华为的忠实用户我先给出自己看法:畅连目前暂时无法取代微信下面我们来具体分析一下畅连是什么畅连就是就是华为近年在新版EMUI加入的畅连通话功能,……4个随手就做的家务习惯,清洁没那么难,干净省钱又轻松在家里住时间久了,总是感觉家里不够干净整洁,每天从早上到晚上一直想要保持干净,但是怎么打扫?感觉非常难!毕竟一个干净整洁的家庭,每个人都会喜欢。有一个爱干净的朋友,她家的……自从有了5G,4G网速就越来越慢?随着5G的到来,很多人直观地感受到了4G的速度越来越慢,于是便怀疑:运营商会不会为了推广5G,故意降低4G的网速?先说答案:运营商不会刻意降速,但5G的部署确实可能会影响……元宇宙的本质是什么?元宇宙的本质:元宇宙是由物质世界、信息世界互相影响、互相促进的虚拟共生的世界,既二元平行世界。元宇宙首先带给这个世界的核心驱动力,是数字平行世界的一次宇宙大爆炸,进而引发虚实共……大数据时代的个体世界既是喧闹的也是安静的,大多数个体都有倾诉的冲动,但回归内心又渴望安静。无论是是喧闹的还是安静的,我们或多或少在这个网络时代留下痕迹,而这些痕迹都会汇集成数据流,漫步在任何地……折叠屏手机成了,三星GalaxyZFold35G,首次荣获五关于折叠屏手机,很多小伙伴都是持观望态度。在笔者看来,出现这种情况,无外乎这几点原因。首先呢,折叠屏手机价格比较贵,大多都在万元以上,高昂的价格,让不少用户望而却步……华为手机和小米手机的品控哪个比较好?整体上都很强,细分来看,小米的软件更强。小米的手机操作系统米柚,英文名叫MIUI,MI是小米公司,UI是用户界面的意思。它是多次迭代的产品,而且在研发和升级的过程中……腾讯设共同富裕主题配捐日筹4。3亿元,尝试第三次分配数字化探本文来源:时代周报作者:郑栩彤自8月18日宣布投资500亿元启动共同富裕专项计划,腾讯逐步推进计划落地。9月6日,时代周报记者从腾讯相关负责人处了解到,腾讯新增共同……SpringCloudAlibabaSpringBoot微服目前微服务开发框架基本上都是采用SpringCloud,但是由于Eureka已经不再开源,所以在服务注册与发现慢慢都不再采用Eureka了,而是转到阿里的Nacos上了。因为N……笔记本电脑的声卡驱动在哪里声卡驱动就是指多媒体声卡控制程序,英文名为SoundCardDriver。驱动程序,英文名为DeviceDriver,全称为设备驱动程序,是一种可以使计算机和设备通信的特殊程序……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网