node.js 无疑是近几年来很火爆到技术,特别是移动互联网的迅速发展 ,node.js的最大特点就是异步单线程 ,有很多优秀的开源框架 比如web 的express
结合谷歌V8引擎 加载js 实现和底层c代码直接交互,底层用到libuv 这里粗略的分析下node.js模块加载 和 底层事件循环
一、node.cc
int Start(int argc, char** argv) {
PlatformInit();
CHECK_GT(argc, 0);
// Hack around with the argv pointer. Usedfor process.title = "blah".
argv = uv_setup_args(argc, argv);
// This needs to run *before*V8::Initialize(). The const_cast is not
// optional, in case you're wondering.
int exec_argc;
const char** exec_argv;
Init(&argc, const_cast<constchar**>(argv), &exec_argc, &exec_argv);
#if HAVE_OPENSSL
// V8 on Windows doesn't have a good sourceof entropy. Seed it from
// OpenSSL's pool.
V8::SetEntropySource(crypto::EntropySource);
#endif
const int thread_pool_size = 4;
default_platform =v8::platform::CreateDefaultPlatform(thread_pool_size);
V8::InitializePlatform(default_platform);
V8::Initialize();
int exit_code = 1;
{
NodeInstanceDatainstance_data(NodeInstanceType::MAIN,
uv_default_loop(),
argc,
const_cast<const char**>(argv),
exec_argc,
exec_argv,
use_debug_agent);
StartNodeInstance(&instance_data);
exit_code = instance_data.exit_code();
}
V8::Dispose();
delete default_platform;
default_platform = nullptr;
delete[] exec_argv;
exec_argv = nullptr;
return exit_code;
}
node.cc 里面的start函数是node.js的入口函数
PlatformInit(); 做一些初始化的工作 设置信号屏蔽
const int thread_pool_size = 4; // 设置线程池大小
default_platform= v8::platform::CreateDefaultPlatform(thread_pool_size);
V8::InitializePlatform(default_platform);
V8::Initialize();
这里是V8里面创建的线程池大小为4
这个 default_platform 就是后面StartNodeInstance 启动node.js里面的代码
static void StartNodeInstance(void*arg) 这个函数
这个函数里面创建一个isolate V8虚拟机 获取堆对象 (js对象)
里面通过 CreateEnvironment创建js执行环境
生成一个env
通过env执行js代码调用底层c函数
//主进程里面是一个无限循环
do {
v8::platform::PumpMessageLoop(default_platform, isolate);
more = uv_run(env->event_loop(), UV_RUN_ONCE);
if (more == false) {
v8::platform::PumpMessageLoop(default_platform, isolate);
EmitBeforeExit(env);
// Emit `beforeExit` if the loop became alive either afteremitting
// event, or after running some callbacks.
more = uv_loop_alive(env->event_loop());
if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
more = true;
}
} while (more == true);
这里就是整个消息循环
PumpMessageLoop 调度空闲线程从消息队列里处理等待执行事件
然后进入uv_run uv_run是libuv里面event loop
一直循环监听事件 处理事件注册的callback
通过env->event_loop() 返回一个监视器 uv_loop_s 结构体 这里面包括有注册的callback等等
uv_run都是围绕这个监视器
具体uv_run里面包括定时器 延时队列 和 优先队列
一些IO耗时任务放到延时队列里面
}