yocto-sumo源码解析(十): ProcessServer.idle_commands

这一节开始介绍ProcessServer.idle_commands,前面我们知道ProcessServer.main就是不停调用idle_commands()以获取可用的套接字描述符或者是文件描述符来进行处理。

    def idle_commands(self, delay, fds=None):
        nextsleep = delay                                                              #设置本函数的下次睡眠延迟                                                                  
        if not fds:
            fds = []

        for function, data in list(self._idlefuns.items()):                            #遍历_idlefuns,逐个调用其中的函数,注李意这里一个技巧,拷贝构造了_idlefuns列表,如果不拷贝直接使用,那么循环体内的删除操作将会出错
            try:
                retval = function(self, data, False)
                if retval is False:                                                    #函数返回值为False,也就是一个逻辑假的时候,从列表中删除这个函数,并设置nextsleep为None
                    del self._idlefuns[function]
                    nextsleep = None
                elif retval is True:                                                   #函数返回值为True,也就是逻辑真的时候,设置nextsleep为None,注意这里不删除所调用的函数,那么我们可以理解为,一个函数被持续调用,直至其返回值为假
                    nextsleep = None
                elif isinstance(retval, float) and nextsleep:                          #若返回值为浮点类型,那么认为这个函数返回的是一个时延,选择一个较小时延给nextsleep
                    if (retval < nextsleep):
                        nextsleep = retval
                elif nextsleep is None:                                                #nextsleep为None,那么直接进入下一个函数的处理流程
                    continue
                else:                                                                  #否则认为函数返回一个文件描述符列表
                    fds = fds + retval
            except SystemExit:
                raise
            except Exception as exc:
                if not isinstance(exc, bb.BBHandledException):
                    logger.exception('Running idle function')
                del self._idlefuns[function]
                self.quit = True
        #上面循环主要是做两件事:一件事是调用所有idlefunc,第二件是找到一个最小的nextsleep # Create new heartbeat event? now = time.time() if now >= self.next_heartbeat:                                            #当前事件比心跳时间迟,认为丢失了心跳 # We might have missed heartbeats. Just trigger once in # that case and continue after the usual delay. self.next_heartbeat += self.heartbeat_seconds if self.next_heartbeat <= now: self.next_heartbeat = now + self.heartbeat_seconds                #计算出一个新的心跳延迟,保障新的心跳延迟一定是在将来 heartbeat = bb.event.HeartbeatEvent(now)               bb.event.fire(heartbeat, self.cooker.data)                            #触发新的心跳 if nextsleep and now + nextsleep > self.next_heartbeat:                   #睡眠以后可能错过新的心跳,因此这里缩短睡眠时间 # Shorten timeout so that we we wake up in time for # the heartbeat. nextsleep = self.next_heartbeat - now if nextsleep is not None:                                                 #在睡眠周期内找到可用的文件描述符,这里需要对select有一定了解 if self.xmlrpc: nextsleep = self.xmlrpc.get_timeout(nextsleep) try: return select.select(fds,[],[],nextsleep)[0] except InterruptedError: # Ignore EINTR return [] else: return select.select(fds,[],[],0)[0]

 从上面的代码分析中,可以看出来,ProessServer.main()中的ready是从fds或者是xmlrpc中选出来的,回首前程往事:

        fds = [self.sock]
        if self.xmlrpc:
            fds.append(self.xmlrpc)

 只要sock就绪,那么就会进入到ready列表。

这里接下来看看_idlefuns这个列表到底是些什么函数呢?ProcessServer在构造函数中初始是置空的,但是提供了一个函数去注册idlefun:

    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
        self.lastui = False
        self.xmlrpc = False

        self._idlefuns = {}

        self.bitbake_lock = lock
        self.sock = sock
        self.sockname = sockname

    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

进而在ProcessServer.start中将该函数传递到configuration对象:

    def _startServer(self):
        print(self.start_log_format % (os.getpid(), datetime.datetime.now().strftime(self.start_log_datetime_format)))
        server = ProcessServer(self.bitbake_lock, self.sock, self.sockname)
        self.configuration.setServerRegIdleCallback(server.register_idle_function)
......
cookerdata.py:
    def setServerRegIdleCallback(self, srcb):
        self.server_register_idlecallback = srcb

 通篇检索yocto-sumo,系统共注册了下面函数:_process_inotify_updates,buildFileIdle,buildTargetsIdle,runCommands

下回再对这些函数进行分说。

 

转载于:https://www.cnblogs.com/shortnil/p/9885555.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值