yocto-sumo源码解析(九): ProcessServer.main

前面讲到BitbakeServer实际上是一个ProcessServer,因此对ProcessServer进行了一个大略的分析集,这里着重再介绍一下ProcessServer.main。

1. 初始化

    def main(self):
        self.cooker.pre_serve()                                                                  #调用cooker.pre_serve(),进入服务前的一些动作,这个后面继续分解
 
        bb.utils.set_process_name("Cooker")                                                      #设置本进程名称为“Cooker”

        ready = []                                                                               #声明一个列表,这个列表从后文看列应该是一个套接字描述符列表

        self.controllersock = False                                                              #声明本服务为非控制器套接字
        fds = [self.sock]                                                                        #将本服务套接字添加进文件描述符列表fds
        if self.xmlrpc:
            fds.append(self.xmlrpc)                                                              #若支持xmlrpc,那么将xmlrpc同样放入文件描述符列表
        print("Entering server connection loop")                                                 #即将进入服务器连接循环

        def disconnect_client(self, fds):                                                        #定义一个断开客户连接的函数,后面会要用到                                                       
            if not self.haveui:
                return
            print("Disconnecting Client")                                                  
            fds.remove(self.controllersock)                                                      #从文件描述符列表中删除控制器套接字描述符                                                   
            fds.remove(self.command_channel)                                                     #从文件描述符列表中删除命令通道套接字描述符,从这两处并列的删除步骤看,服务器接受两个套接字
            bb.event.unregister_UIHhandler(self.event_handle, True)                              #从事件处理器中删除本事件处理器
            self.command_channel_reply.writer.close()                                            #关闭命令通道写端
            self.event_writer.writer.close()                                                     #关闭事件写端
            del self.event_writer                                                                #析构事件作者
            self.controllersock.close()                                                          #控制器套接字关闭
            self.controllersock = False
            self.haveui = False
            self.lastui = time.time()
            self.cooker.clientComplete()                                                         #调用cooker.clientComplete函数,后面再进行分解
            if self.timeout is None:
                print("No timeout, exiting.")
                self.quit = True

2. 服务器连接循环

        while not self.quit:
            if self.sock in ready:                                                               #假设本套接字在ready列表,那么从本套接字接受一个控制器套接字连入,初始本套接字并不在ready列表
                self.controllersock, address = self.sock.accept()
                if self.haveui:
                    print("Dropping connection attempt as we have a UI %s" % (str(ready)))
                    self.controllersock.close()
                else:
                    print("Accepting %s" % (str(ready)))
                    fds.append(self.controllersock)                                              #将控制器套接字添加到文件描述符列表
            if self.controllersock in ready:                                                     #若控制器套接字就绪,则从控制器套接字接受新的ui文件描述符
                try:
                    print("Connecting Client")
                    ui_fds = recvfds(self.controllersock, 3)                                     #根据控制器套接字中取3个套接字,分别用于事件作者,命令通道作者,命令通道读者

                    # Where to write events to
                    writer = ConnectionWriter(ui_fds[0])                                         #新建连接作者,用于事件处理
                    self.event_handle = bb.event.register_UIHhandler(writer, True)               #新建本事件处理器
                    self.event_writer = writer

                    # Where to read commands from
                    reader = ConnectionReader(ui_fds[1])                                         #新建连接命令通道读者
                    fds.append(reader)                                                           #将读者添加进文件描述符列表
                    self.command_channel = reader

                    # Where to send command return values to
                    writer = ConnectionWriter(ui_fds[2])                                         #新建连接命令通道作者,用于向客户发出回应
                    self.command_channel_reply = writer

                    self.haveui = True

                except (EOFError, OSError):
                    disconnect_client(self, fds)                                                 #出现异常则断开客户连接

            if not self.timeout == -1.0 and not self.haveui and self.lastui and self.timeout and                     (self.lastui + self.timeout) < time.time():
                print("Server timeout, exiting.")
                self.quit = True

            if self.command_channel in ready:                                                    #命令通道就绪,从命令通道中读取一条命令
                try:
                    command = self.command_channel.get()
                except EOFError:
                    # Client connection shutting down
                    ready = []
                    disconnect_client(self, fds)                                                 #出现异常则断开客户连接
                    continue
                if command[0] == "terminateServer":
                    self.quit = True
                    continue
                try:个
                    print("Running command %s" % command)
                    self.command_channel_reply.send(self.cooker.command.runCommand(command))    #执行接收到的命令并且构造响应                except Exception as e:                   logger.exception(‘Exception in server main event loop running command %s (%s)‘ % (command, str(e)))

            if self.xmlrpc in ready:                                                            #xmlrpc就绪,处理xmlrpc请求。                self.xmlrpc.handle_requests()                                         

            ready = self.idle_commands(.1, fds)                                                 #从套接字中获取就绪的套接字

3. 退出清理

        print("Exiting")
        # Remove the socket file so we don‘t get any more connections to avoid races
        os.unlink(self.sockname)                                                                #删除域套接字文件
        self.sock.close()                                                                       #关闭本套接字,这里顺序上存疑

        try:
            self.cooker.shutdown(True)                                                          #关闭cooker
            self.cooker.notifier.stop()                                                         #停止notify
            self.cooker.confignotifier.stop()                                                   #停止confignotify
        except:
            pass

        self.cooker.post_serve()                                                                #调用cooker.post_serve(),这个在后面进行分解

        # Finally release the lockfile but warn about other processes holding it open
        lock = self.bitbake_lock                               
        lockfile = lock.name
        lock.close()                                                                            #关闭bitbake_lock
        lock = None

        while not lock:
            with bb.utils.timeout(3):
                lock = bb.utils.lockfile(lockfile, shared=False, retry=False, block=True)
                if not lock:
                    # Some systems may not have lsof available
                    procs = None
                    try:
                        procs = subprocess.check_output(["lsof", ‘-w‘, lockfile], stderr=subprocess.STDOUT)
                    except OSError as e:
                        if e.errno != errno.ENOENT:
                            raise
                    if procs is None:
                        # Fall back to fuser if lsof is unavailable
                        try:
                            procs = subprocess.check_output(["fuser", ‘-v‘, lockfile], stderr=subprocess.STDOUT)
                        except OSError as e:
                            if e.errno != errno.ENOENT:
                                raise

                    msg = "Delaying shutdown due to active processes which appear to be holding bitbake.lock"
                    if procs:
                        msg += ":\n%s" % str(procs)
                    print(msg)
                    return
        # We hold the lock so we can remove the file (hide stale pid data)
        bb.utils.remove(lockfile)
        bb.utils.unlockfile(lock)

原文地址:https://www.cnblogs.com/shortnil/p/9866808.html

时间: 2024-11-05 18:27:15

yocto-sumo源码解析(九): ProcessServer.main的相关文章

ReactiveSwift源码解析(九) SignalProducerProtocol延展中的Start、Lift系列方法的代码实现

上篇博客我们聊完SignalProducer结构体的基本实现后,我们接下来就聊一下SignalProducerProtocol延展中的start和lift系列方法.SignalProducer结构体的方法扩展与Signal的扩展相同,都是面向协议的扩展.首先创建了一个SignalProducerProtocol协议,使SignalProducer在延展中遵循SignalProducerProtocol协议.然后我们再对SignalProducerProtocol进行扩展.这样一来,SignalP

Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析

王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 腾讯微云:http://url.cn/TnGbdC 360云盘:http://yunpan.cn/cQ4c2UALDjSKy 访问密码 45e2土豆:http://www.tudou.com/programs/view/NGgUD5FBQaA/优酷:http://v.youku.com/v_show/id_

Mybaits 源码解析 (九)----- 全网最详细,没有之一:一级缓存和二级缓存源码分析

像Mybatis.Hibernate这样的ORM框架,封装了JDBC的大部分操作,极大的简化了我们对数据库的操作. 在实际项目中,我们发现在一个事务中查询同样的语句两次的时候,第二次没有进行数据库查询,直接返回了结果,实际这种情况我们就可以称为缓存. Mybatis的缓存级别 一级缓存 MyBatis的一级查询缓存(也叫作本地缓存)是基于org.apache.ibatis.cache.impl.PerpetualCache 类的 HashMap本地缓存,其作用域是SqlSession,myBat

Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例

概要  前面,我们已经学习了ArrayList,并了解了fail-fast机制.这一章我们接着学习List的实现类——LinkedList.和学习ArrayList一样,接下来呢,我们先对LinkedList有个整体认识,然后再学习它的源码:最后再通过实例来学会使用LinkedList.内容包括:第1部分 LinkedList介绍第2部分 LinkedList数据结构第3部分 LinkedList源码解析(基于JDK1.6.0_45)第4部分 LinkedList遍历方式第5部分 LinkedL

【特征匹配】RANSAC算法原理与源码解析

转载请注明出处:http://blog.csdn.net/luoshixian099/article/details/50217655 随机抽样一致性(RANSAC)算法,可以在一组包含"外点"的数据集中,采用不断迭代的方法,寻找最优参数模型,不符合最优模型的点,被定义为"外点".在图像配准以及拼接上得到广泛的应用,本文将对RANSAC算法在OpenCV中角点误匹配对的检测中进行解析. 1.RANSAC原理 OpenCV中滤除误匹配对采用RANSAC算法寻找一个最佳

Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例

java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 概要 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解ArrayList.先对ArrayLis

【转】Java 集合系列12之 TreeMap详细介绍(源码解析)和使用示例

概要 这一章,我们对TreeMap进行学习.我们先对TreeMap有个整体认识,然后再学习它的源码,最后再通过实例来学会使用TreeMap.内容包括:第1部分 TreeMap介绍第2部分 TreeMap数据结构第3部分 TreeMap源码解析(基于JDK1.6.0_45)第4部分 TreeMap遍历方式第5部分 TreeMap示例 转载请注明出处:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3310928 第1部

【转】Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例

概要 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解ArrayList.先对ArrayList有个整体认识,再学习它的源码,最后再通过例子来学习如何使用它.内容包括:第1部分 ArrayList简介第2部分 ArrayList数据结构第3部分 ArrayList源码解析(基于JDK1.6.0_45)第4部分 ArrayList遍历方式第5部分 toArray

Android EventBus3.0使用及源码解析

叨了个叨 最近因为换工作的一些琐事搞的我一个头两个大,也没怎么去学新东西,实在是有些愧疚.新项目用到了EventBus3.0,原来只是听说EventBus的鼎鼎大名,一直没仔细研究过.趁着周末有些时间,研究下代码,也算没有虚度光阴. EventBus GitHub : https://github.com/greenrobot/EventBus EventBus3.0简介 EventBus是greenrobot出品的一个用于Android中事件发布/订阅的库.以前传递对象可能通过接口.广播.文件

Andfix热修复框架原理及源码解析-上篇

热补丁介绍及Andfix的使用 Andfix热修复框架原理及源码解析-上篇 Andfix热修复框架原理及源码解析-下篇 1.不知道如何使用的同学,建议看看我上一篇写的介绍热补丁和Andfix的使用,这样你才有一个大概的框架.通过使用Andfix,其实我们心中会有一个大概的轮廓,它的工作原理,大概就是,所谓的补丁文件,就是通过打包工具apkpatch比对新的apk和旧的apk之间的差异.然后让我们的旧包运行的时候,就加载它,把以前的一些信息替换掉.我们现在就抱着这个大方向去深入源码探个究竟!!首先