node源码详解(二 )—— 运行机制 、整体流程
本作品采用知识共享署名 4.0 国际许可协议进行许可。转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource2
本博客同步在https://cnodejs.org/topic/56e3be21f5d830306e2f0fd3
本博客同步在http://www.cnblogs.com/papertree/p/5225201.html
2.1 项目代码结构
node 主要的部分有4个【下图最左列就是node项目源码(4.2.2)的根目录】:
1. 原生 js模块:node提供给 用户js 代码的类接口,平时用的require('fs')、require('http')调用的都是这部分的代码。【最左列的 lib文件夹,展开后是左二列】
2. node 源码:node程序的main函数入口;还有提供给lib模块的C++类接口。【最左列的 src 文件夹,展开后是第三列】
3. v8引擎:node用来解析、执行js代码的运行环境。【最左列的deps文件夹展开后是第四列,v8和libuv等依赖都放在这里】
4. libuv:事件循环库,提供最底层的 io操作接口(包括网络io操作的epoll_wait()、文件异步io的线程池管理)、事件循环逻辑。 【第四列的uv文件夹,展开后是第五列】
记住这几个路径:
./lib
./src
./deps/uv

图2-1-1
2.2 运行流程
下图4个红色序号分别对应着上篇博客提出的4个问题所在位置。后续博客分说。
接下来对一些关键地方进行说明:
1. 核心数据结构 default_loop_struct (结构体为struct uv_loop_s,后续祥讲)
这个数据结构是事件循环的核心。当node执行到“加载js文件”这个步骤(结合下图)时,用户的js代码如果有io操作:
那么js代码通过调用 -》lib模块(2.1 中的原生js模块)-》C++模块(2.1中的源码部分) -》 libuv接口(2.1中deps/uv部分) -》最终的系统api,拿到系统返回的一个fd(文件描述符),和 js代码传进来的回调函数callback,封装成一个io观察者(一个uv__io_s类型的对象),保存到default_loop_struct;
2. 进入事件循环
当处理完 js代码,如果有io操作,那么这时default_loop_struct是保存着对应的io观察者的。
处理完js代码,main函数继续往下调用libuv的事件循环入口uv_run(),node进程进入事件循环:
uv_run()的while循环做的就是一件事,判断default_loop_struct是否有存活的io观察者。
a. 如果没有io观察者,那么uv_run()退出,node进程退出。
b. 而如果有io观察者,那么uv_run()进入epoll_wait(),线程挂起等待,监听对应的io观察者是否有数据到来。有数据到来调用io观察者里保存着的callback(js代码),没有数据到来时一直在epoll_wait()进行等待。
这里解答了博客(一)的“问题2”的一部分:为什么console.log()的js代码导致node退出,而server.listen(80)导致线程挂起等待。
3. 这里一旦没搞清逻辑就有个疑问:
第2点说在uv_run()里面如果监听的io观察者有数据到来,那么调用对应的callback,执行js代码。如果没有数据到来,一直在epoll_wait()等待。那如果我js代码里面有新的 io操作想要交给epoll_wait()进行监听,而此刻监听着的io观察者又没有数据到来,线程一直在这里等待,那怎么办?
首先第1点讲到,执行js代码的时候,通过调用node提供的C++接口最终把io观察者都保存到default_loop_struct里面,js代码执行完之后,node继续运行才进入epoll_wait()等待。也就是说node在epoll_wait()的时候,js代码执行完毕了。而js代码的回调函数部分,本来的设定就是在epoll_wait()监听的io观察者被触发之后才会执行回调,在epoll_wait()进行等待的时候,不可能存在“有新io操作要交给epoll_wait()去监听”这样的js代码。

图2-2-1
node源码详解(二 )—— 运行机制 、整体流程的更多相关文章
- node源码详解(四) —— js代码如何调用C++的函数
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource4 本博客同步在https://cnodejs.o ...
- node源码详解(四)
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource4 本博客同步在https://cnodejs.o ...
- node源码详解(五) —— 在main函数之前 —— js和C++的边界,process.binding
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource5 本博客同步在https://cnodejs.o ...
- node源码详解 (一)
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource1 本博客同步在https://cnodejs.o ...
- node源码详解(五)
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource5 本博客同步在https://cnodejs.o ...
- node源码详解(三)—— js代码在node中的位置,process、require、module、exports的由来
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource3 本博客同步在https://cnodejs.o ...
- node源码详解(三)
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource3 本博客同步在https://cnodejs.o ...
- node源码详解(七) —— 文件异步io、线程池【互斥锁、条件变量、管道、事件对象】
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource7 本博客同步在https://cnodejs.o ...
- node源码详解(六) —— 从server.listen 到事件循环
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource6 本博客同步在https://cnodejs.o ...
随机推荐
- GtkImageMenuItem
做了个工具条,每次点arrow出来的菜单都没图标,郁闷;查来查去,看源码,看css,最后知道GtkAction缺省就是对应GtkImageMenuItem,再一试,跟toolbar无关,换menu也不 ...
- iOS中4种判断网络请求的方式(系统状态栏、AFNetworking、Reachability、自定义)
iOS 实时判断网络状态 方法一:利用系统状态栏判断网络状态 // 状态栏是由当前app控制的,首先获取当前app UIApplication *app = [UIApplication shared ...
- 【HighCharts系列教程】五、版权属性——Credits
一.Credits属性说明 严格来讲,Credits并不算版权信息,官方的说法是:Highchart by default putsa credits label in the lower right ...
- 高效PHP编程
1.尽量静态化: 如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍. 当然了,这个测试方法需要在十万级以上次执行,效果才明显. 其实静态方法和非静 ...
- 理解MySQL——索引与优化(转)
转自:http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html 写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库 ...
- [算法] dijkstra单源无负权最小路径算法
#include <stdio.h>#include <stdlib.h>#include <string.h> #define INF 1000000#defin ...
- 我的云服务之WWW
云服务器系统是:[root@ip-172-31-27-132 system]# cat /etc/redhat-release Red Hat Enterprise Linux Server rele ...
- 类似java.lang.NoClassDefFoundError: org/jaxen/JaxenException解决方法
在使用dom4j的xpath时出现java.lang.NoClassDefFoundError: org/jaxen/JaxenException的异常,原因是dom4j引用了jaxen jar包,而 ...
- Servlet实现文件上传(多文件)(三)
1.上传文件的页面fileUpload2.jsp <%@ page language="java" import="java.util.*" pageEn ...
- MySQL中 InnoDB 和 MyISAM 小结
转:http://blog.csdn.net/ithomer/article/details/5136982 部分内容: InnoDB和MyISAM的差别 InnoDB和MyISAM是许多人在使用My ...