• HHVM源码剖析


    一、前言

    hhvm源码中充满了很多C++11的新特性,并且使用了各种设计模式如工厂,模板方法等,利用智能指针包裹指针,让delete没有肆意的出现

    模板,继承,explicit,纯虚函数的出现令代码中充满了惊喜

    例如下面这段代码:run_函数是pthread_create执行的函数

     NewImage

     

    二、hhvm启动流程总览

    hhvm/main.cpp

    NewImage

    75行:调用execute_program函数进行具体的逻辑

     

    runtime/base/program-functions.cpp 

    NewImage

    885行:调用execute_program_impl进行具体的逻辑

     

    runtime/base/program-functions.cpp 

    NewImage

    1260:  从配置文件中加载配置项

    1475:函数负责启动线程与接收处理请求

     

    总体流程图如下:

     

    NewImage

     

    RuntimeOption::Load函数负责加载配置文件中的配置项

    start_server函数负责启动线程与接收处理请求

     

    三、Load函数配置文件的加载与处理

     

    以如下配置项的解析为例

    Server{
    Type= FastCGIServer
    ThreadCount=20
    ###......
    }

     

    runtime/base/runtime-option.cpp

    NewImage

    782-801行 解析配置文件中Server块中的内容

    787行 将配置文件中的type值FastCGIServer赋值给ServerType

    800行 将配置文件中的ThreadCount赋值给ServerThreadCount

    所以ServerType的值为FastCGIServer

    ServerThreadCount的值为20

    四、start_server初始化HttpServer对象

    runtime/base/program-functions.cpp 

    NewImage

    799行  初始化HttpServer对象

    837行 启动server,接受处理请求

    httpserver对象的初始化函数

     

    runtime/server/http-server.cpp 

    NewImage

    88行 KNumProcessors为系统内核的个数,通过62行的 const int kNumProcessors = sysconf(_SC_NPROCESSORS_ONLN);获得

    84-90行:如果配置的thread大于系统的内核的个数,则在启动时只启动与系统内核个数相同的thread数,将其余的个数赋值给additionalThreads

    92行:调用工厂函数,针对ServerType:FastCGIServerc生成一个工厂对象

    96-101行:将配置文件中的信息赋值给options对象,注意这里的startingThreadCount最大为系统内核的个数

    102行:根据options配置信息生成一个Server

     

     

    runtime/server/fastcgi/fastcgi-server-factory.cpp 

    NewImage

    听过FastCGIServerFactory工厂生成一个FastCGIServer对象

     

    FastCGIServer的构造函数

    runtime/server/fastcgi/fastcgi-server.cpp  

    NewImage

    这里的worker就是启动的线程数目

     

    这里关注一下m_dispatcher的初始化

     

    runtime/server/fastcgi/fastcgi-server.h 

    JobQueueDispatcher<FastCGIWorker> m_dispatcher;   

    m_dispatcher的类型为JobQueueDispatcher

     

    FastCGIWorker的定义如下:

    typedef ServerWorker<std::shared_ptr<FastCGIJob>,FastCGITransportTraits> FastCGIWorker;

     

    struct ServerWorker  : JobQueueWorker<JobPtr,Server*,true,false,JobQueueDropVMStack>{}//传入的第三个参数为true

    template<typename TJob, typename TContext = void*, bool countActive = false, bool waitable = false, class Policy = detail::NoDropCachePolicy> 
    class JobQueueWorker {}

    ServerWorker的继承关系如下

    NewImage

    所以这里的countActive为true

    NewImage

    467-473行:由于CountActivewe== true所以不会进入下方的逻辑中

    util/job-queue.h

    NewImage

    656-658行 同样由于CountActive== true 因此不会走入656-658行里面

     

     

    五、start_server RunOrExitProcess启动一个Server

    runtime/server/http-server.cpp 

    NewImage 

    262-268行 由于没有配置 ThreadDocuments,ThreadLoopDocuments所以size()大小为0 不会走入

    269行 ServerPort的初始化值为80,只要配置文件中的Port值不为0(即使配置文件中没有Server.Port值,也会初始化为80) 就会走入

    runtime/base/runtime-option.cpp

    121 int RuntimeOption::ServerPort = 80; 

    相比之下

    AdminServer.Port的值初始化为0

    runtime/base/runtime-option.cpp

    266 int RuntimeOption::AdminServerPort = 0; 

    因此只有配置了才会启动AdminServer

     

    runtime/server/http-server.cpp

    NewImage

    非AdminServer的时候 传入的pageServer==true因为走入579行

    这里的m_pageServer为fastcgi-server对象

     

     

    runtime/server/fastcgi/fastcgi-server.cpp 

    NewImage

    263行 m_worker.start()通过C++11的thread启动一个线程负责网络IO

    264行 m_dispatcher.start() 通过pthread_create启动若干线程负责CPU部分

     

    下面看一看m_dispatcher.start的详细逻辑

    util/job-queue.h  

    NewImage

    513-516行 如果配置的threadCount过小的话 这里会进行增加

    517-520行 通过start()函数创建线程

     

    util/job-queue.h 

    NewImage

     

    util/async-func.h 

    NewImage

    AsyncFunc继承自AsyncFuncImpl

    AsnycFuncImpl实现了start()函数

     

    NewImage

    util/async-func.cpp

    NewImage

    至此线程启动完毕,线程运行的函数为ThreadFunc

     

    六、ThreadFunc从何而来

    ThreadFunc是从那里来的呢?

    util/async-func.cpp

    NewImage

     

    NewImage

     

    NewImage

    这里使用了模板方法设计模式

    util/async-func.h

    一段神奇的代码.....

    NewImage

     

    util/job-queue.h

    NewImage

     

    最终执行的方法如下

    NewImage

    NewImage

    NewImage

     

     

     

    我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan

  • 相关阅读:
    【大数据学习与分享】技术干货合集
    K8S集群搭建
    字节跳动面试难吗,应该如何应对?(含内推方式)
    我的新书《C++服务器开发精髓》终于出版啦
    同事内推的那位Linux C/C++后端开发同学面试没过......
    死磕hyperledger fabric源码|Order节点概述
    死磕以太坊源码分析之EVM如何调用ABI编码的外部方法
    死磕以太坊源码分析之EVM动态数据类型
    死磕以太坊源码分析之EVM固定长度数据类型表示
    死磕以太坊源码分析之EVM指令集
  • 原文地址:https://www.cnblogs.com/magicsoar/p/8168701.html
Copyright © 2020-2023  润新知