![0395e3ec385b672e5923ed12eb7ac66e.png](https://img-blog.csdnimg.cn/img_convert/0395e3ec385b672e5923ed12eb7ac66e.png)
本文同步发表在:
nodejs深入学习系列之libuv基础篇(一)blog.5udou.cn![622f779c37642f910532c818a6fd71d6.png](https://img-blog.csdnimg.cn/img_convert/622f779c37642f910532c818a6fd71d6.png)
学习完nodejs基石之一的v8基础篇(还没看过的童鞋请跳转到这里:nodejs深入学习系列之v8基础篇),我们这次将要继续学习另外一块基石:libuv。关于libuv的设计思想,我已经翻译成中文,还没看过的童鞋还是请跳转到这里: [译文]libuv设计思想概述,如果还没看完这篇文章的童鞋,下面的内容也不建议细看了,因为会有”代沟“的问题~
本文的所有示例代码都可以在这个仓库中找到: libuv-demo
1、libuv入门介绍
libuv是一个跨平台聚焦于异步IO的库,著名的event-loop便是libuv的一大特色。我们要学习Libuv,那么就要先掌握libuv的编译。
1.1、libuv的编译简单介绍
和v8一样,libuv的编译简单概括如下:
- 先下载GYP:
git clone https://chromium.googlesource.com/external/gyp build/gyp
- 指定ninja:
./gyp_uv.py -f ninja
- 编译:
ninja -C out/Debug
- 跑测试:
./out/Debug/run-tests
1.2、libuv简单使用
利用编译好的libuv库文件,我们可以开始写一个简单又经典的例子: Hello world。
#include "stdio.h"
#include "uv.h"
int main() {
uv_loop_t *loop = uv_default_loop();
printf("hello libuv");
uv_run(loop, UV_RUN_DEFAULT);
}
喜欢动手的童鞋可以下载一开始提到的demo,其中的hello_libuv.c
便是,利用如何正确地使用v8嵌入到我们的C++应用中这篇文章讲到的运行方式,我们借助CLion
软件和CMakeLists.txt
文件来编译所有的demo模块,这方面就不再赘述了,记得将CMakeLists.txt
文件中的include_directories
和link_directories
改成你在第一小节编译出来的Libuv静态库文件的目录位置。
好了,有了上面的基础之后,我们开始结合demo来入门这个深藏众多秘密的代码库。接下去的文章可能会比较长,一次读不完的话建议收藏起来,多读几次~
2、libuv的基础概念介绍与实践
看懂libuv之前,我们需要理解下面这些概念,并用实际用例来测试这些概念。
2.1、event-loop线程
我们都知道线程是操作系统最基本的调度单元,而进程是操作系统的最基本的资源分配单元,因此可以知道进程其实是不能运行,能运行的是进程中的线程。进程仅仅是一个容器,包含了线程运行中所需要的数据结构等信息。一个进程创建时,操作系统会创建一个线程,这就是主线程,而其他的从线程,都要在主线程的代码来创建,也就是由程序员来创建。因此每一个可执行的运用程序都至少有一个线程
于是libuv一开始便启动了event-loop线程,再在这个主线程上利用线程池去创建更多的线程。在event-loop线程中是一段while(1)
的死循环代码,直到没有活跃的句柄的时候才会退出,这个时候libuv进程才被销毁掉。清楚这点对于后面的学习至关重要。
2.2、Handle
中文翻译为句柄,如[译文]libuv设计思想概述一文所属,整个libuv的实现都是基于Handle和Request。所以理解句柄以及libuv提供的所有句柄实例才能够真的掌握libuv。按照原文所述,句柄是:
表示能够在活动时执行某些操作的长生命周期对象。
理解这句话的意思,首先我们抓住两个关键词:长生命周期、对象。Libuv所有的句柄都需要初始化,而初始化都会调用类似这种函数:uv_xxx_init
。xxx
表示句柄的类型ÿ