本文将从 源代码 研究nodejs 的原理、本质,探讨nodejs的应用场景,以及高性能开发实践指南。

文件夹:

第一节:编译node.js

第二节:源代码分析

进入主题:下面是在win7 64 下进行,其它平台编译 。请參见官网。

第一节:编译node.js,过程非常easy

1、下载源代码。  git clone https://github.com/joyent/node

假设没有安装gitclient,能够在打开https://github.com/joyent/node  点击 Download ZIP,进行下载

2、安装 Python 2.6 or 2.7 和 Visual Studio 2010 or 2012。我这里是 Python
2.7.8  和 Visual Studio 2012

3、进入node文件夹
 运行 vcbuild release

大概
10多分钟 就能够编译成功。在Release文件夹下会生成node.exe。以下是我编译成功的图。

第二节:源代码分析

我们在IDE 中 打开刚才的node文件夹,方便我们看源代码。

我这里是Idea查看。

benchmark : 一些nodejs 性能測试 代码

build:编译nodejs 生成文件夹

Debug:编译nodejs 生成文件夹

Release:编译nodejs 生成文件夹

deps:nodejs依赖 的工具包。包含 v8、http_parser、opensslzlib、zlib、uv。

。。

doc:文档

lib:包括JavaScript源代码

src:包括C++源代码

test:測试代码

tools:编译时用到的工具

这里我们仅仅需关注 src 和lib 目录。

1、从node.cc 文件 看 node进程 启动过程的

int Start(int argc, char** argv) {
const char* replaceInvalid = getenv("NODE_INVALID_UTF8"); if (replaceInvalid == NULL)
WRITE_UTF8_FLAGS |= String::REPLACE_INVALID_UTF8; #if !defined(_WIN32)
// Try hard not to lose SIGUSR1 signals during the bootstrap process.
InstallEarlyDebugSignalHandler();
#endif assert(argc > 0); // Hack around with the argv pointer. Used for 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<const char**>(argv), &exec_argc, &exec_argv); #if HAVE_OPENSSL
// V8 on Windows doesn't have a good source of entropy. Seed it from
// OpenSSL's pool.
V8::SetEntropySource(crypto::EntropySource);
#endif int code;
V8::Initialize();
{
Locker locker(node_isolate);
Isolate::Scope isolate_scope(node_isolate);
HandleScope handle_scope(node_isolate);
Local<Context> context = Context::New(node_isolate);
Environment* env = CreateEnvironment(
node_isolate, context, argc, argv, exec_argc, exec_argv);
// Assign env to the debugger's context
if (debugger_running) {
HandleScope scope(env->isolate());
env->AssignToContext(v8::Debug::GetDebugContext());
}
// This Context::Scope is here so EnableDebug() can look up the current
// environment with Environment::GetCurrent().
// TODO(bnoordhuis) Reorder the debugger initialization logic so it can
// be removed.
{
Context::Scope context_scope(env->context());
bool more;
do {
more = uv_run(env->event_loop(), UV_RUN_ONCE);
if (more == false) {
EmitBeforeExit(env); // Emit `beforeExit` if the loop became alive either after emitting
// 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);
code = EmitExit(env);
RunAtExit(env);
}
env->Dispose();
env = NULL;
} CHECK_NE(node_isolate, NULL);
node_isolate->Dispose();
node_isolate = NULL;
V8::Dispose(); delete[] exec_argv;
exec_argv = NULL; return code;
}

Environment* CreateEnvironment(Isolate* isolate,
Handle<Context> context,
int argc,
const char* const* argv,
int exec_argc,
const char* const* exec_argv) {
HandleScope handle_scope(isolate); Context::Scope context_scope(context);
Environment* env = Environment::New(context); uv_check_init(env->event_loop(), env->immediate_check_handle());
uv_unref(
reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
uv_idle_init(env->event_loop(), env->immediate_idle_handle()); // Inform V8's CPU profiler when we're idle. The profiler is sampling-based
// but not all samples are created equal; mark the wall clock time spent in
// epoll_wait() and friends so profiling tools can filter it out. The samples
// still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
// TODO(bnoordhuis) Depends on a libuv implementation detail that we should
// probably fortify in the API contract, namely that the last started prepare
// or check watcher runs first. It's not 100% foolproof; if an add-on starts
// a prepare or check watcher after us, any samples attributed to its callback
// will be recorded with state=IDLE.
uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
uv_check_init(env->event_loop(), env->idle_check_handle());
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_prepare_handle()));
uv_unref(reinterpret_cast<uv_handle_t*>(env->idle_check_handle())); if (v8_is_profiling) {
StartProfilerIdleNotifier(env);
} Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate);
process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "process")); Local<Object> process_object = process_template->GetFunction()->NewInstance();
env->set_process_object(process_object); SetupProcessObject(env, argc, argv, exec_argc, exec_argv);
Load(env); return env;
}

void SetupProcessObject(Environment* env,
int argc,
const char* const* argv,
int exec_argc,
const char* const* exec_argv) {
HandleScope scope(env->isolate()); Local<Object> process = env->process_object(); process->SetAccessor(env->title_string(),
ProcessTitleGetter,
ProcessTitleSetter); // process.version
READONLY_PROPERTY(process,
"version",
FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION)); // process.moduleLoadList
READONLY_PROPERTY(process,
"moduleLoadList",
env->module_load_list_array()); // process.versions
Local<Object> versions = Object::New(env->isolate());
READONLY_PROPERTY(process, "versions", versions); const char http_parser_version[] = NODE_STRINGIFY(HTTP_PARSER_VERSION_MAJOR)
"."
NODE_STRINGIFY(HTTP_PARSER_VERSION_MINOR);
READONLY_PROPERTY(versions,
"http_parser",
FIXED_ONE_BYTE_STRING(env->isolate(), http_parser_version)); // +1 to get rid of the leading 'v'
READONLY_PROPERTY(versions,
"node",
OneByteString(env->isolate(), NODE_VERSION + 1));
READONLY_PROPERTY(versions,
"v8",
OneByteString(env->isolate(), V8::GetVersion()));
READONLY_PROPERTY(versions,
"uv",
OneByteString(env->isolate(), uv_version_string()));
READONLY_PROPERTY(versions,
"zlib",
FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION)); const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION);
READONLY_PROPERTY(
versions,
"modules",
FIXED_ONE_BYTE_STRING(env->isolate(), node_modules_version));

void Load(Environment* env) {
HandleScope handle_scope(env->isolate()); // Compile, execute the src/node.js file. (Which was included as static C
// string in node_natives.h. 'natve_node' is the string containing that
// source code.) // The node.js file returns a function 'f'
atexit(AtExit); TryCatch try_catch; // Disable verbose mode to stop FatalException() handler from trying
// to handle the exception. Errors this early in the start-up phase
// are not safe to ignore.
try_catch.SetVerbose(false); Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(), "node.js");
Local<Value> f_value = ExecuteString(env, MainSource(env), script_name);
if (try_catch.HasCaught()) {
ReportException(env, try_catch);
exit(10);
}
assert(f_value->IsFunction());
Local<Function> f = Local<Function>::Cast(f_value); // Now we call 'f' with the 'process' variable that we've built up with
// all our bindings. Inside node.js we'll take care of assigning things to
// their places. // We start the process this way in order to be more modular. Developers
// who do not like how 'src/node.js' setups the module system but do like
// Node's I/O bindings may want to replace 'f' with their own function. // Add a reference to the global object
Local<Object> global = env->context()->Global();

大致的过程是这种 :

载入 V8 、OpenSSL ...

创建 Environment 环境

设置 Process 进程对象

运行 node.js 文件

2、从 node.js 文件 看 global 配置过程。吐槽一下,nodejs的源代码写的太搓了。C系语言出生的风格?

这个文件大致是 是配置 全局变量、配置process、定义模块对象。

后面将深入 解说
node.js 这个文件 、以及结合 src 的C++类,与lib 下的 js代码 解说nodejs。

我们能够得出一个结论: nodejs  = node API + V8;

编译nodejs及其源代码研究的更多相关文章

  1. 编译CDH Spark源代码

    如何编译CDH Spark源代码 经过漫长的编译过程(我编译了2个半小时),最终成功了,在assembly/target/scala-2.10目录下面有spark-assembly-1.0.0-cdh ...

  2. 通过分析 JDK 源代码研究 TreeMap 红黑树算法实现

    本文转载自http://www.ibm.com/developerworks/cn/java/j-lo-tree/ 目录: TreeSet 和 TreeMap 的关系 TreeMap 的添加节点 Tr ...

  3. NodeJs读取源代码使用的字符集

    今天用NodeJs写了个简单的客户端/服务器程序,并让客户端向服务器发送汉字.当在Windows上执行客户端时,发现服务器端打印的接收到的数据是乱码.后来发现Windows上的客户端文件的储存编码方案 ...

  4. 关于tcc、tlink的编译链接机制的研究

    1.学习过程 在c:\下建立文件夹c,并将编译器tcc.exe.连接器tlink.exe.相关文件c0s.obj.cs.lib.emu.lib.maths.lib放入文件夹中. 要搭建一个简单的C语言 ...

  5. 【hadoop之翊】——CentOS6.5 Linux上面编译Hadoop2.4源代码

    今天来说说编译hadoop源代码的事情吧~ 1.首先下载源代码 地址:http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-2.4.0/ 2.加压t ...

  6. LIVE555源代码研究之四:MediaServer (一)

    LIVE555源代码研究之四:MediaServer (一) 从本篇文章開始我们将从简单server程序作为突破点,深入研究LIVE555源代码. 从前面的文章我们知道.不论什么一个基于LIVE555 ...

  7. 在Ubuntu 16.04上编译OpenJDK8的源代码

    本文将详细介绍在Ubuntu16.04上对OpenJDK8进行编译. 1.准备编译环境 使用的操作系统为Ubuntu16.04,如果读者没有安装Ubuntu,可以在Windows上使用虚拟机的方式进行 ...

  8. 源码编译Nodejs 4.6 on CentOS6

    1.本来是要按照个newman程序,无奈newman必须要node版本>=4,所以不得不安装node4.6 下载地址:https://nodejs.org/dist/v4.6.0/node-v4 ...

  9. 重编译Linux命令源代码

    转: http://blog.csdn.net/endoresu/article/details/6967435 以su命令为例. 查看su命令的路径: # which su /bin/su 查看su ...

随机推荐

  1. 8.Maven之(八)约定优于配置

    转自:“https://blog.csdn.net/qq_25460531/article/details/79423961” maven的配置文件看似很复杂,其实只需要根据项目的实际背景,设置个别的 ...

  2. 无阻塞加载外部js(动态脚本元素,XMLHttpRequest注入,LazyLoad)

    动态脚本元素即在js中去创建<script>标签加载外部js并执行,这样加载的好处是文件的下载和执行过程不会阻塞页面的其他进程.通过下面两个例子对比出效果 <!DOCTYPE htm ...

  3. Flask项目之手机端租房网站功能测试(完结)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 目录 一丶注册和登录以及用户退出功能 二丶上传头像功能和修改用户名功能测试 三丶发布房源以及实名认证功能测试 四丶网站房屋搜索功能 ...

  4. 洛谷——P1012 拼数

    https://www.luogu.org/problem/show?pid=1012#sub 题目描述 设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数. 例如:n=3时,3个整 ...

  5. Activity启动过程源代码分析

    事实上写分析源代码文章总会显得非常复杂非常乏味,可是梳理自己看源代码时的一些总结也是一种提高. 这篇博客分析下Activity启动过程源代码,我会尽量说得简单点. 个人的观点是看源代码不能看得太细,否 ...

  6. 妙味css3课程---1-1、css中自定义属性可以用属性选择器么

    妙味css3课程---1-1.css中自定义属性可以用属性选择器么 一.总结 一句话总结:可以的. 1.如何实现用属性选择器实现a标签根据href里面含有的字段选择背景图片? p a[href*=te ...

  7. cocos2d-x中六种持续性动作

    持续性动作: (一) 位置变化动作 Move by to Jump by to (二) 属性变化动作 Scale by to Rotate by to Fade in out to Tint to b ...

  8. C++ 中的异或操作^

    好好的利用异或能够产生奇妙的效果. 异或运算的性质: 不论什么一个数字异或它自己都等于0.也就是说.假设我们从头到尾依次异或数组中的每个数字,那么终于的结果刚好是那个仅仅出现一次的数字.由于那些出现两 ...

  9. 【Codeforces Round #299 (Div. 2) E】Tavas and Pashmaks

    [链接] 我是链接,点我呀:) [题意] 游泳+跑步比赛. 先游泳,然后跑步. 最先到终点的人是winner. 但是现在游泳的距离和跑步的距离长度都不确定. S和R. 给你n个人,告诉你每个人游泳的速 ...

  10. 硬件——STM32 , SN74HC573锁存器

    74HC573是一款高速CMOS器件: 上图中:输出使能为:OE   锁存使能为:LE 典型电路: 上图中:PWR-AL-0,PWR-AL-1,PWR-AL-2:是单片机输出的高低电平给573 对应的 ...