yocto-sumo源码解析(八): ProcessServer
从前面章节的论述中,我们知道BitBakeServer实际上是一个ProcessServer,什么是ProcessServer不可不了解。
1. 类的声明: 首先这是一个python的多进程包里面的进程子类,关于多进程包可以参阅:https://docs.python.org/2/library/multiprocessing.html,在api的使用上尽量保持和多线程使用习惯一致。
class ProcessServer(multiprocessing.Process):
2. 构造函数:初始化一系列成员变量,变量命名非常易懂,这里在代码块里面进行注释
def __init__(self, lock, sock, sockname): multiprocessing.Process.__init__(self) self.command_channel = False #命令通道,从名字上看应该是用于接收命令请求的。 self.command_channel_reply = False #命令通道响应,从名字上看应该是用于构造命令响应的。 self.quit = False #服务是否需要退出。 self.heartbeat_seconds = 1 # default, BB_HEARTBEAT_EVENT will be checked once we have a datastore.
#心跳包间隔。 self.next_heartbeat = time.time() #下次心跳时间。 self.event_handle = None #事件处理 self.haveui = False #是否有ui self.lastui = False #上次ui self.xmlrpc = False #xmlrpc,这个估计用于远程过程调用。 self._idlefuns = {} #空闲函数字典 self.bitbake_lock = lock #bitbake实例锁,从这个成员看,ProcessServer的设计似乎还是偏向于给bitbake专用。 self.sock = sock #套接字,从前面上下文看,可能是域套接字。 self.sockname = sockname #套接字名字
3. 注册空闲函数:
def register_idle_function(self, function, data): """Register a function to be called while the server is idle""" assert hasattr(function, '__call__') self._idlefuns[function] = data
4. run函数:对于这个,熟悉多线程的应该很有似曾相识的感觉:
def run(self): #若xmlrpcinterface[0]不为None,或者不为False,那么建立BitBakeXMLRPCServer,应该是为了远程模式。 if self.xmlrpcinterface[0]: self.xmlrpc = bb.server.xmlrpcserver.BitBakeXMLRPCServer(self.xmlrpcinterface, self.cooker, self) print("Bitbake XMLRPC server address: %s, server port: %s" % (self.xmlrpc.host, self.xmlrpc.port))
#设置心跳包间隔时长。 heartbeat_event = self.cooker.data.getVar('BB_HEARTBEAT_EVENT') if heartbeat_event: try: self.heartbeat_seconds = float(heartbeat_event) except: bb.warn('Ignoring invalid BB_HEARTBEAT_EVENT=%s, must be a float specifying seconds.' % heartbeat_event)
#设置服务器超时时长。 self.timeout = self.server_timeout or self.cooker.data.getVar('BB_SERVER_TIMEOUT') try: if self.timeout: self.timeout = float(self.timeout) except: bb.warn('Ignoring invalid BB_SERVER_TIMEOUT=%s, must be a float specifying seconds.' % self.timeout) #向锁文件写入拥有该锁的pid,如果是远程模式,同时写入主机名和端口号。 try: self.bitbake_lock.seek(0) self.bitbake_lock.truncate() if self.xmlrpc: self.bitbake_lock.write("%s %s:%s\n" % (os.getpid(), self.xmlrpc.host, self.xmlrpc.port)) else: self.bitbake_lock.write("%s\n" % (os.getpid())) self.bitbake_lock.flush() except Exception as e: print("Error writing to lock file: %s" % str(e)) pass
#调用main函数,如果配置了画像模式则建立画像流程。 if self.cooker.configuration.profile: try: import cProfile as profile except: import profile prof = profile.Profile() ret = profile.Profile.runcall(prof, self.main) prof.dump_stats("profile.log") bb.utils.process_profilelog("profile.log") print("Raw profiling information saved to profile.log and processed statistics to profile.log.processed") else: ret = self.main() return ret