HHVM源码剖析

1、前言

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

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

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

 NewImage

 

2、hhvm启动流程总览

hhvm/main.cpp函数

NewImage

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

 

runtime/base/program-functions.cpp 源码分析

NewImage

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

 

runtime/base/program-functions.cpp spa

NewImage

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

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

 

整体流程图以下:

 

NewImage

 

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

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

 

3、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

4、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行里面

 

 

5、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

 

6、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

相关文章
相关标签/搜索