要写一个application,首先要一个xxx.app文件,里面写有application的相关信息,比如我要写一个名为game的application,那么我就可以写一个game.app,
{application,game,[{description,""},{vsn,"1"},{modules,[]},{registered.[]},{applications,[kernel,stdlib]},{mod,{game_app,[]}}]} modules里面的内容在使用systool打包时会用到,applications里面包含了那些必须在该application启动之前启动的application,systool使用这个来生成正确的脚本,mod里面包含了回调模块。
启动时我们就可以像这样application:start(game),这样就会去调用game_app模块下的start函数,game_app的behaviour为application,他必须支持start()和stop()函数,start()返回{ok,pid},pid是顶层supervisor的pid。
调用supervisor:start_link(supname,module,args)就可以启动一个supervisor,这时会去调用module:init(args)函数,如果init()成功返回,那么这个函数会返回{ok,pid},pid是supervisor自己的pid,所以根据这个可以很简单的把supervisor挂在application下。
init()函数需要返回{ok,{supflags,child_spec}},具体来举一个例子:{ok,{{one_for_one,4,4},[{game,{game,start_link,[]},tempory,5000,worker,[game]}]}},注意supflags如果是simple_one_for_one,子进程此时是不会创建的,必须要手动调用supervisor:start_child(SupRef, ChildSpec)才能创建,而且child_spec在simple模式下只能有且仅有一个,oneforone模式 可以有0或多个。
这个函数在simple_one_for_one模式和one_for_one模式有不同的表现,这个函数在simple_one_for_one模式下childspec是定义在module:init(Args)下的,他会根据init中的childspec来启动进程,此时的start_child中的childspec应该填写一个List,调用时会自动将该List与childSpec中的启动参数做++操作;如果子进程的启动函数返回值是{ok,pid},那么子进程将会加入到该supervisor下
在one_for_one模式下,start_child/2中的childspec就是真的childspec。有些在sup的init函数 也提供了childspec,这个参数是在调用start_link的时候直接启动one模式进程使用的,使用start_chile启动的进程还是以该函数的参数为准。
gen_server:stark_link()会调用module:init(),init()返回一个状态state,start_link一直等待直到init()返回,其返回值是{ok,pid},pid是gen_server本身