一、前言

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

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

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

二、hhvm启动流程总览

hhvm/main.cpp

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

runtime/base/program-functions.cpp 

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

runtime/base/program-functions.cpp 

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

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

总体流程图如下:

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

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

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

以如下配置项的解析为例

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

runtime/base/runtime-option.cpp

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

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

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

所以ServerType的值为FastCGIServer

ServerThreadCount的值为20

四、start_server初始化HttpServer对象

runtime/base/program-functions.cpp 

799行  初始化HttpServer对象

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

httpserver对象的初始化函数

runtime/server/http-server.cpp 

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 

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

FastCGIServer的构造函数

runtime/server/fastcgi/fastcgi-server.cpp  

这里的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的继承关系如下

所以这里的countActive为true

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

util/job-queue.h

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

五、start_server RunOrExitProcess启动一个Server

runtime/server/http-server.cpp 

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

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

这里的m_pageServer为fastcgi-server对象

runtime/server/fastcgi/fastcgi-server.cpp 

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

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

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

util/job-queue.h  

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

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

util/job-queue.h 

 

util/async-func.h 

AsyncFunc继承自AsyncFuncImpl

AsnycFuncImpl实现了start()函数

util/async-func.cpp

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

六、ThreadFunc从何而来

ThreadFunc是从那里来的呢?

util/async-func.cpp

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

util/async-func.h

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

util/job-queue.h

最终执行的方法如下

HHVM源码剖析的更多相关文章

  1. jQuery之Deferred源码剖析

    一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...

  2. Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现

    声明:本文为原创博文,转载请注明出处. Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线程 ...

  3. Apache Spark源码剖析

    Apache Spark源码剖析(全面系统介绍Spark源码,提供分析源码的实用技巧和合理的阅读顺序,充分了解Spark的设计思想和运行机理) 许鹏 著   ISBN 978-7-121-25420- ...

  4. 基于mybatis-generator-core 1.3.5项目的修订版以及源码剖析

    项目简单说明 mybatis-generator,是根据数据库表.字段反向生成实体类等代码文件.我在国庆时候,没事剖析了mybatis-generator-core源码,写了相当详细的中文注释,可以去 ...

  5. STL"源码"剖析-重点知识总结

    STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...

  6. SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现

    SpringMVC完成初始化流程之后,就进入Servlet标准生命周期的第二个阶段,即“service”阶段.在“service”阶段中,每一次Http请求到来,容器都会启动一个请求线程,通过serv ...

  7. 自己实现多线程的socket,socketserver源码剖析

    1,IO多路复用 三种多路复用的机制:select.poll.epoll 用的多的两个:select和epoll 简单的说就是:1,select和poll所有平台都支持,epoll只有linux支持2 ...

  8. Java多线程9:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

  9. JS魔法堂:mmDeferred源码剖析

    一.前言 avalon.js的影响力愈发强劲,而作为子模块之一的mmDeferred必然成为异步调用模式学习之旅的又一站呢!本文将记录我对mmDeferred的认识,若有纰漏请各位指正,谢谢.项目请见 ...

随机推荐

  1. C# Code First 实例学习

    Code First是Entity Framework提供的一种新的编程模型.通过Code First我们可以在还没有建立数据库的情况下就开始编码,然后通过代码来生成数据库.下面具体讲解一下,在操作的 ...

  2. springboot + redis缓存使用

    [参照资料] 1.spring boot 官网文档 2.https://www.cnblogs.com/gdpuzxs/p/7222309.html [项目结构] [pom.xml配置] <?x ...

  3. jsp运行原理及运行过程

    JSP的执行过程主要可以分为以下几点: 1)客户端发出请求. 2)Web容器将JSP转译成Servlet源代码. 3)Web容器将产生的源代码进行编译. 4)Web容器加载编译后的代码并执行. 5)把 ...

  4. java并发包下的并发工具类

    1.Exchanger 功能:用于线程间数据的交换 应用场景:1)遗传算法,目前还不是特别理解  2)校对工作,假设A,B线程做同一件任务,可以通过数据校验判断两线程是否正确的工作 例子:是一个简单的 ...

  5. 从零开始,轻松搞定SpringCloud微服务系列

    本系列博文目录 [微服务]之一:从零开始,轻松搞定SpringCloud微服务系列–开山篇(spring boot 小demo) [微服务]之二:从零开始,轻松搞定SpringCloud微服务系列–注 ...

  6. Spring Cloud Ribbon 整合 Hystrix

    在前面随笔 Spring Cloud 之 Ribbon 的ribbon工程基础上进行改造 1.pom.xml 加入依赖 <dependency> <groupId>org.sp ...

  7. 这个接口管理平台 eoLinker 开源版部署指南你一定不想错过

    本文主要内容是讲解如何在本地部署eoLinker开源版. 环境要求 1.PHP 5.5+ / PHP7+(推荐) 2.Mysql 5.5+ / Mariadb 5.5+ 3.Nginx(推荐) / A ...

  8. CF Round#436 div2

    额,这次的题目其实挺智障的.所以通过这次比赛,我也发现了自己是一个智障.... 不说太多,说多是泪... A. Fair Game 题意:给你一个数组,看你能否把它均分为两个所有元素均相同的子数组. ...

  9. dva + antd + mockjs 实现基础用户管理

    1.安装dva-cli npm install dva-cli -g 2.创建应用 dva new dvadashboard   [dvadashboard为项目名]       3.安装mockjs ...

  10. iscroll4 input textarea不能获得焦点问题

    最近在做移动端项目的时候,使用iscroll4实现页面滚动效果,之后发现页面中的input,textarea等不能得到焦点,输入内容. 问题原因是: 使用iscroll之后,输入框无法聚焦,页面文字等 ...