闲聊c/c++ 4: 征服优雅、高效的Libuv库之初识篇

这一系列文章主要分析nodejs中的核心库Libuv。


我的参考书:

朴灵的深入浅出nodejs

Jeffrey Richter的Windows核心编程

Anthony Williams的C++并发编程实战

reference.png

暂定为四篇:

1) 征服之初识篇(背景基础以及重要的概念,图示)
2) 征服之进展篇(libuv的编译,例子,内部用到的c语言技巧以及QUEUE的使用)
3) 征服之高潮篇(线程池,iocp,同步,并发,线程间的通信等)
4) 征服之和谐篇(Libuv的初始化,主循环,主线程和线程池之间的和谐交往)

通过征服Libuv系列文章,目的是让大家了解:

1) C语言之美(语法简单,功能强大,贴近硬件,适合系统级别编程,有很多技巧)
2) 多线程与线程的同步技术
3) 线程池技术
4) windows IOCP技术
5) 了解与ms PPL, intel TBB以及libdispatch(ios gcd)之间的异同点和优缺点。
6) vs c++中多线程下的debug技巧

之所以称为了解,而不是掌握,是因为这些技术偏向于底层的系统编程,并不是一撮而就的,需要一定的时间和经历才能沉淀下来的。因此只能说是让大家了解。

为了简单期间,一些限制条件:

仅关注windows下的实现
仅重点分析libuv的通用cpu密集型计算的框架,了解cpu密集计算框架,实际上异步io就比较容易理解了
因为windows下,异步io通过IOCP(完成端口),会使代码实现非常简单,而效率非常高。

在写此篇blog时,突然感觉到,是不是应该将libuv库进行拆分,将核心部分代码抽离出来单独运行,这样的好处就是要分析的代码量要少很多,仅关注我们感兴趣的代码,有利于演示。

还有一个目的:
就是在简化精华版的基础上升级一下,看看是否能够实现任务的动态均衡(ms PPL库和intel TBB库都有动态均衡,Work Stealing的功能,libuv目前确定没有此功能,libdispatch目前没发现,源码正在阅读中,还没看到)。这个实现难度还是很大的,就当练练手吧,哈哈

我尝试一下吧,看看是否可行!


1、背景:

前段时间,完成了一个微信项目,在后台选型过程中,花了将近一个月考察了java,php几个库,但最终却选择了nodejs,原因很简单:

1、java的配置实在是太麻烦了
2、php实在不熟悉,特别扭
3、nodejs使用js编程,我本人还是比较熟悉js的基础部分(不算es6.0 es7.0标准),并且npm真好用,实在是资源太丰富了,有时选择太多也是一种痛苦啊!
4、nodejs基于异步io技术,效率非常高。而且分布式部署简单。

通过无数次的比较,最终选定了令我非常满意的组合,感觉最起码少写了80%的代码。

后台配套方案:

framework: strongloop/loopback(被IBM收购了,只能说强大无比)
朴灵的: wechat / wechat-api / wechat-oauth
supersheep: wechat-pay
数据库: mongodb用于不需要事务处理的表 mysql用于支付的事务处理
因为没经验,在支付时需要事务处理,所以调整为使用mysql。不过从另外一个角度说明loopback的强大,支持多数据源的统一api操作。

前台配套方案:

angularjs1.x
jquery

总体而言,该前后台配套系统的开发非常令人愉悦。前台不好统计,但是微信后台,至少少写了80%代码!!

我正在做loopback方面的demo,来分享一下loopback框架和angularjs之间的互动,你会看到他们的配合是多么的默契。
近期会有blog以及demo提交github


2、演变:

目前基于异步回调的开发非常盛行,例如ios中的gcd,android中的基于接口回调方式。如果有过这些开发经验,你会觉得nodejs的异步事件开发模型还是蛮熟悉的。

随着逐渐熟悉nodejs,深深的喜欢上了nodejs,因此更想深入的了解一下nodejs是如何实现的。

通过了解nodejs的代码结构,结合深入浅出nodejs第三章的异步io所示流程图,逐步验证其正确性。特别是看到libuv中具有深厚c语言功底的老鸟所写的代码,忍不住想与大家分享c的代码之美!!

题外话:我深入研究过的或正在研究的以及即将研究的c源码库

随便说一下:现在c/c++貌似不太流行了。但是不管如何,c语言我认为是一门基础语言,每个程序员如果想要深入了解底层,最好学一下c语言。

我本人很喜欢c语言,曾经花了5年以上的时间自己研究3D游戏之父-约翰卡马克quake系列引擎以及sgi opengl1.21实现(This is SGI's Sample Implementation of the OpenGL API. It is both a reference implementation and a driver framework used by **almost all commercial 3D hardware vendors **to develop hardware drivers for their systems)。

可以说quake引擎以及opengl源码是形成我科学程序观的基石,是技术源。(差点说成科学发展观了,这个太....)

目前正在阅读调试的c库源码:

libdispatch ios gcd中的函数都是来源于libdispatch,目前已经都移植到linuxwindows中了

libuv 跨平台的异步io和work

已编译并运行过demo,计划要阅读的c源码库:

libkqueue 一个跨平台的unix kqueue实现。实际在libdispatch移植到windows和linux版本时,就包含了libkqueue。因为libdispatch(源于macos和ios,他们都是基于unix系统的)基于kqueue实现。

libzmq跨平台的异步消息队列库(内部c++实现,以c api方式导出,很多库也使用这种方式)

zookeeper是一个分布式应用程序协调服务,是Hadoop和Hbase的重要组件。目前作为单独一个库独立出来了。

libuv目前基本了解整个流程了,其他几个等弄明白了,也一起分享吧,让我们一起来学c语言!

为什么选这些库:
1) 提高自身编程水平最好的方式是多阅读经典源码
2) 多线程,异步以及分布式、异步消息队列等都是目前主流,这些库是最高水平的实现,被大规模,广泛使用。
3) 这些库都是跨平台库,代码量不大,并且实用性又很高,功能单一,这就是c库的魅力所在。
4) 都是c语言实现,借助于ide的帮助,会很容易了解清楚整个流程。

3、libuv是什么?

官方介绍:

  libuv is a multi-platform support library with a focus on asynchronous I/O. 
  It was primarily developed for use by Node.js

由上面的介绍,我们可以知道:

1) 跨平台:windows linux unix都支持
2) 异步io:windows IOCP 、linux epoll、unix kqueue
3) 主要目的是用于nodejs,实际还有很多库或程序使用了libuv
   例如目前风头正劲的跨平台.NetCore库(就是曾经大名鼎鼎的微软的asp.net)也是使用libuv作为核心
4) libuv不仅仅支持异步io操作,而且还具有一个强劲的线程池,用于支持多线程并行的cpu密集型操作。
   这个才是我们重点要分析的模块

4、nodejs、google v8 javascript引擎和libuv之间的关系:

1) nodejs主要由google v8 javascript引擎和libuv组成
2) v8引擎绑定libuv实现的api,因此,既能使用ecma js标准语言来执行js代码,又能通过js调用libuv相关接口。
3) 由此可见,libuv本身是独立的c语言库,既可以直接使用c/c++来调用,也可以被绑定到c#(.NetCore)或者其他任何语言,例如java ,lua......
   c/c++实现的库最大的好处就是能被各种其他编程语言所绑定和调用。
   因为其他各种编程语言基本都是用c/c++来实现的,都留有接口与c/c++互调。

借用朴灵 深入浅出nodejs中的两张图来了解整个流程:

朴灵-深入浅出nodejs-架构图.png
朴灵-深入浅出nodejs-异步调用示意图.png

我们libuv源码分析以上图为指导,深入挖掘每个细节,验证其正确性,从而掌握整个libuv的精髓!

请将此图看上100遍,背出来,肯定有非常大帮助


nodejs就是数据通过v8引擎(主线程:数据输入)传递给Libuv进行处理(线程池:数据处理--根据数据类型不同,io数据由IOCP[windows]线程池处理,通用计算则由自己实现的线程池处理),libuv处理好后通知v8引擎我已经完成了,你来进行完成处理(主线程:完成回调,信息输出)。


其实从上面的叙述可以了解到以下几点:
1) v8 javascript引擎是单线程的,数据的输入,信息的输出(完成回调)都是在主线程中处理。这一点以后在源码分析中我们可以验证,通过vs强大的debug功能,我们可以很清晰的看到具体代码到底是运行在哪个线程中。
2) 但是数据处理模块(libuv)不是单线程的,它根据数据请求类型是否是io请求(socket,文件读写或管道等)还是work请求(非io请求)。不同的请求使用不同的处理策略。例如io请求,在windows下用IOCP,在linux下用epool。而work请求,windows和linux下都是使用统一的,自己实现的线程池。而我们的源码分析就是要证明上面的描述。


下一篇: 征服libuv之进展篇

.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容