Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node源码粗读(4):process对象底层实现 #12

Open
xtx1130 opened this issue Dec 21, 2017 · 5 comments
Open

node源码粗读(4):process对象底层实现 #12

xtx1130 opened this issue Dec 21, 2017 · 5 comments

Comments

@xtx1130
Copy link
Owner

xtx1130 commented Dec 21, 2017

这篇文章主要对process对象底层的实现进行解读,所读的源码为9.2版本的代码,博文之中相关代码链接为博文发布之日的node主干分支的代码。

process的诞生

process的实现代码应该还是很容易看懂的,我们直接切到node.cc中寻找定义process的方法,用不了很长时间,你会发现SetupProcessObject方法,通过函数名就能很直观的发现这是定义process的地方,我们直接走到逻辑中去一窥究竟。
这段代码里重复最多的有两个地方,一个是宏READONLY_PROPERTY,另一个则是函数env->SetMethod(Environment::SetMethod)。其中不难发现,宏定义中调用的是obj->DefineOwnProperty,是用来给process定义方法的,而函数SetMethod调用的是:

 v8::Local<v8::Function> function =
      NewFunctionTemplate(callback)->GetFunction();
  const v8::NewStringType type = v8::NewStringType::kInternalized;
  v8::Local<v8::String> name_string =
      v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
  that->Set(name_string, function);
  function->SetName(name_string);

相信如果做过读者addon的话,对这段代码应该是比较熟悉了,可以看到,SetMethod是用来给process定义方法用的。

process在c++中的初始化

process在c++中的初始化操作则是在env.cc,大家可以注意一下它的外层函数为 Environment::Start

void Environment::Start(int argc,
                        const char* const* argv,
                        int exec_argc,
                        const char* const* exec_argv,
                        bool start_profiler_idle_notifier) {
//....
SetupProcessObject(this, argc, argv, exec_argc, exec_argv);
//....
}

接下来我们来看一下node.cc中的start函数:
issue12-1
在这里我标注出来了两个地方,一个是env.Start 是对 Environment::Start的调用;而另一个则是LoadEnvironment(&env);LoadEnvironment之前已经介绍过了,在这里跟大家重温一段代码:

Local<Value> arg = env->process_object();
auto ret = f->Call(env->context(), Null(env->isolate()), 1, &arg);

在这里我们可以看到process作为了参数传入到了f中(Call为 Function::Call,f是Funciton的实例,其中包含了node入口文件bootstrap_node.js以及一坨代码还有从内存中拿出来的编译好的内置js文件),到此为止,我们可以看到c++正式把process抛出给js了。而process在这之前进行c++中的初始化,便可以很好的保证了抛出给bootstrap_node.js的process可用。

在bootstrap_node.js中的process

bootstrap_node.js 其实就是一个匿名函数,当然咯,也是所有js文件的“鼻祖”。如果读者简单或者不小心点开了./lib/internal/bootstrap_node.js,映入眼帘的第一行代码就是……注释。好了,看主要内容:那么很快你就会发现:

(function(process) {
//....
});

这就是bootstrap_node.js。重点在于我这个匿名函数居然还有个参数--process,联想一下我刚才分析的f->Call,然后你就会发现,原来这里接住了c++中吐出来的process。这时候我开始有点慌了……说好的全局的process呢?别着急,如果读者了解bootstrap_node,就肯定会知道,它里面有一个方法setupGlobalVariables ,其中就包含了:

global.process = process;

至此,整个process的过程就分析完了,process中还有几个比较重要的api,比如binding、std系列,以及还有moduleLoadList的生成,如果有时间的话,会继续给大家详细解剖。

@ghost
Copy link

ghost commented Dec 21, 2017

qq 20171204150947

@gnipbao
Copy link

gnipbao commented Jan 5, 2018

可以分析下Event Loop相关模块么🐱

@xtx1130
Copy link
Owner Author

xtx1130 commented Jan 5, 2018

@gnipbao 感觉这没啥可分析的啊。。。node源码层面涉及到的很少:开局一个uv_default_loop。。。后面全靠libuv。不过可以分析下lib库里面的timers,进而延伸到libuv,等下下篇文章吧,哈哈,下篇要写什么我已经想好了。

@sunstdot
Copy link

简约不简单,给大佬跪下了

@xtx1130
Copy link
Owner Author

xtx1130 commented Jan 18, 2018

@sunstdot
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants