
libuv源码分析
文章平均质量分 68
theanarkh
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
在Libuv中使用io_uring
本文介绍如果在Libuv中使用io_uring。逻辑:1 申请一个io_uring对应的fd。2 初始化一个poll handle,封装1中的fd。3 注册到Libuv的epoll中。4 读取文件列表,给io_uring提交请求5 io_uring完成,1中的fd可读,从而epoll返回。6 Libuv的poll io阶段执行回调。7 回调里获取io_uring的任务完成列表,拿到每个任务关联的请求,执行回调。代码如下(参考https://github.com/shuveb/io_uring原创 2021-07-03 05:56:32 · 592 阅读 · 0 评论 -
io_uring和Node.js
前言:io_uring是大神Jens Axboe开发的异步IO框架,在Linux内核5.1引入。本文介绍什么是异步框架和io_uring的一些基础内容,最后介绍Node.js(Libuv)中,之前有人提但至今还没有合并的一个关于io_uring的pr。1 io_uring介绍在io_uring之前,Linux没有成熟的异步IO能力,什么是异步IO呢?回想我们读取资源的过程,我们可以以阻塞或非阻塞的模式调用read、readv,也可以通过epoll监听文件描述符和事件的方式,在回调里调用read系列函数进原创 2021-07-03 02:17:20 · 351 阅读 · 1 评论 -
N-API之Promise篇
本文介绍N-API中的Promise功能的使用。Promise相关的API一共有四个。napi_create_promise // 创建一个Promise,类似new Promisenapi_resolve_deferred // resolve一个Promisenapi_reject_deferred // reject一个Promisenapi_is_promise // 判断变量是否是一个Promise我们首先看一下napi_is_promise。测试代码如下const { isProm原创 2021-06-06 01:24:11 · 975 阅读 · 4 评论 -
nodejs是如何处理tcp连接的
前几天和一个小伙伴交流了一下nodejs中epoll和处理请求的一些知识,今天简单来聊一下nodejs处理请求的逻辑。我们从listen函数开始。int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { // 设置处理的请求的策略,见下面的分析 if (single_accept == -1) { const char* val = getenv("UV_TCP_SINGLE_ACCEPT"); sin原创 2021-02-24 23:47:45 · 378 阅读 · 0 评论 -
通过源码理解http层和tcp层的keep-alive
前言:最近在研究websocket和keep-alive。而websocket涉及到长连接,过多无用的长连接对系统来说是负担,是否可以尽快发现对端是否已经掉线,从而释放这个连接来减少系统压力呢,就这个初衷,通过wireshark和nodejs调试一下心跳机制。引发了一些研究和思考。我们知道建立tcp连接的代价是比较昂贵的,每次连接需要三次握手,还有慢开始,或者建立一个连接只为了传少量数据等都影响了效率。这时候如果能保持连接,那会大大提高效率。但是如果一直保持连接,又没有数据或者有一端已经断网则会浪费资源,原创 2020-07-25 20:56:21 · 295 阅读 · 0 评论 -
Libuv源码分析v0.0.1.pdf
github:https://github.com/theanarkh/read-libuv-code下载:https://11111-1252105172.cos.ap-shanghai.myqcloud.com/Libuv%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90v0.0.1.pdf原创 2020-05-31 01:19:14 · 362 阅读 · 0 评论 -
Libuv介绍
Libuv是什么,可以做什么?Libuv是一个跨平台的的基于事件驱动的异步io库。但是他提供的功能不仅仅是io,包括进程、线程、信号、定时器、进程间通信等。下面是来自官网对Libuv架构的介绍图。从上图中我们看到Libuv使用各平台提供的事件驱动模块实现异步(epoll, kqueue, IOCP, eventports)。他用来支持上层非文件io的模块。libuv把上层的事件和回调封装成io观察者(uv__io_t)放到底层的事件驱动模块。当事件触发的时候,libuv会执行io观察者中的回原创 2020-05-17 23:29:37 · 2243 阅读 · 0 评论 -
libuv之unix域的使用
之前分析了unix域在libuv的基本原理。今天以一个简单的例子看一下如何使用它。本文涉及到一些网络编程的知识,不过文章不打算讲解这些,如果不了解可以先了解一下,或者留言。void remove_sock(int sig) { uv_fs_t req; // 删除unix域对应的路径 uv_fs_unlink(loop, &req, PIPENAME, NULL); // 退出进程 exit(0);}int main() { loop = uv_原创 2020-05-13 00:27:13 · 466 阅读 · 0 评论 -
libuv源码分析之unix域
unix域是一种基于单主机的进程间通信方式。实现模式类似tcp通信。今天先分析他的实现,后续会分析他的使用。在libuv中,unix域用uv_pipe_t表示。struct uv_stream_s { // uv_handle_s的字段 void* data; // 所属事件循环 uv_loop_t* loop; // handle类型 uv_handle_type type; // 关闭handle时的回调 uv_close_cb c原创 2020-05-12 23:09:54 · 394 阅读 · 0 评论 -
理解libuv的基本原理
libuv的实现是一个很经典生产者-消费者模型。libuv在整个生命周期中,每一次循环都执行每个阶段(phase)维护的任务队列。逐个执行节点里的回调,在回调中,不断生产新的任务,从而不断驱动libuv。今天我们分析一下libuv的整体架构,从而学会如何使用libuv。我们从libuv的一个小例子开始。#include <stdio.h>#include <uv.h>int64_t counter = 0;void wait_for_a_while(uv_idle_t*原创 2020-05-08 23:35:22 · 928 阅读 · 0 评论 -
libuv小册之线程池篇
最近开始写小册子,一篇篇来,写完了再整理总结到一起。Libuv是基于事件驱动的异步io库,他本身是一个单进程单线程的。但是难免会有耗时的操作。如果在Libuv的主循环里执行的话,就会阻塞后面的任务执行。所以Libuv里维护了一个线程池。他负责处理Libuv中耗时的操作,比如文件io、dns、用户自定义的耗时任务。文件io因为存在跨平台兼容的问题。无法很好地在事件驱动模块实现异步io。下面分析一下...原创 2020-05-04 14:51:21 · 930 阅读 · 0 评论 -
libuv源码分析之stream第二篇
上一篇分析了流的基础知识和读写操作的实现。今天继续分析。1 关闭流的写端// 关闭流的写端int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { // 流是可写的,并且还没关闭写端,也不是处于正在关闭状态 if (!(stream->flags & UV_HANDL...原创 2020-05-03 16:19:18 · 365 阅读 · 0 评论 -
libuv源码分析之stream第一篇
流的实现在libuv里占了很大篇幅,今天分析一下流的实现。首先看数据结构。流在libuv里用uv_stream_s表示,他属于handle族。继承于uv_handle_s。struct uv_stream_s { // uv_handle_s的字段 void* data; // 所属事件循环 uv_loop_t* loop; // handle类型 ...原创 2020-05-02 16:14:51 · 517 阅读 · 0 评论 -
libuv源码分析之queue
libuv的queue实现得很博大精深。严重考验了c指针的理解。今天就分享一下他的实现。首先从一个typedef开始typedef void *QUEUE[2];这个是c语言中定义类型别名的一种方式。比如我们定义一个变量QUEUE q就相当于void *q[2];即一个数组,他每个元素是void型的指针。下面我们接着分析四个举足轻重的宏定义,理解他们就相当于理解了libuv的...原创 2020-04-24 00:39:11 · 517 阅读 · 2 评论 -
libuv之inotify源码分析
inotify是linux系统提供用于监听文件系统的机制。inotify机制的逻辑大致是1 init_inotify创建一个inotify机制的实例,返回一个文件描述符。类似epoll。2 inotify_add_watch往inotify实例注册一个需监听的文件(inotify_rm_watch是移除)。3 read((inotify实例对应的文件描述符, &buf, sizeof...原创 2020-04-22 00:37:45 · 442 阅读 · 0 评论 -
通过源码分析nodejs的进程架构
我们知道nodejs是单进程(单线程)的,但是nodejs也为用户实现了多进程的能力,下面我们看一下nodejs里多进程的架构是怎么样的。 nodejs提供同步和异步创建进程的方式。我们首先看一下异步的方式,nodejs创建进程的方式由很多种。但是归根到底是通过spawn函数。所以我们从这个函数开始,看一下整个流程。var spawn = expo...原创 2020-03-26 01:13:01 · 382 阅读 · 0 评论 -
nodejs事件循环阶段之close
close是nodejs每轮事件循环中最后的一个阶段。我们看看怎么使用。我们知道对于一个handle,他的使用一般是init,start,stop。但是如果我们在stop一个handle之后,还有些事情需要处理怎么办?这时候就可以使用close阶段。close阶段可以用来关闭一个handle,并且执行一个回调。比如用于释放动态申请的内存。close阶段的任务由uv_close产生。void uv...原创 2020-03-12 13:57:35 · 530 阅读 · 0 评论 -
nodejs事件循环阶段之poll io
poll io是nodejs非常重要的一个阶段,文件io、网络io、信号处理等都在这个阶段处理。这也是最复杂的一个阶段。处理逻辑在uv__io_poll这个函数。这个函数比较复杂,我们分开分析。 开始说poll io之前,先了解一下他相关的一些数据结构。1 io观察者uv__io_t。这个结构体是poll io阶段核心结构体。他主要是保存了io相关...原创 2020-03-10 23:11:29 · 775 阅读 · 0 评论 -
nodejs事件循环阶段之prepare
prepare是nodejs事件循环中的其实其中一个阶段(phase)。属于比较简单的一个阶段。我们知道libuv中分为handle和request。而prepare阶段的任务是属于handle。我们看一下他的定义。下面我们看看怎么使用它void prep_cb(uv_prepare_t *handle) { printf("Prep callback\n");}int mai...原创 2020-03-09 01:23:50 · 489 阅读 · 0 评论 -
ubuntu-18.10下编译和使用libuv
1 github下载源码。2 安装包:apt install automake,apt install libtool3 执行sh autogen.sh,make,make install4 安装完后libuv的头文件和库在/usr/local/libuv文件夹下。编译测试代码。#include <stdio.h>#include <stdlib.h>#incl......原创 2020-02-03 19:15:31 · 957 阅读 · 0 评论 -
libuv源码解析之信号处理
libuv初始化的时候会初始化信号处理相关的逻辑。// 保证只执行uv__signal_global_init一次void uv__signal_global_once_init(void) { uv_once(&uv__signal_global_init_guard, uv__signal_global_init);}static void uv__signal_glob...原创 2020-01-07 22:58:00 · 639 阅读 · 0 评论 -
libuv源码解析之结构体全景图
libuv各结构体的关系和字段的意思全景图(基于linux版本)原创 2020-01-05 20:51:47 · 302 阅读 · 0 评论 -
libuv源码解析之uv_loop_t结构体
原创 2020-01-05 01:15:57 · 481 阅读 · 0 评论 -
libuv线程池和主线程通信原理
一切要从libuv的初始化开始。uv_default_loop();该函数调用uv_loop_init();进行初始化。uv_loop_init有以下代码。uv_async_init(loop, &loop->wq_async, uv__work_done);int uv_async_init(uv_loop_t* loop, uv_async_t* handle...原创 2020-01-04 19:22:28 · 1048 阅读 · 0 评论 -
nodejs源码解析之事件循环
nodejs的的事件循环由libuv的uv_run函数实现。在该函数中执行while循环,然后处理各种阶段(phase)的事件回调。事件循环的处理相当于一个消费者,消费由各业务代码生产的任务。下面看一下代码。int uv_run(uv_loop_t* loop, uv_run_mode mode) { int timeout; int r; int ran_pending; r...原创 2020-01-04 14:43:31 · 434 阅读 · 0 评论 -
nodejs的dns解析源码分析
nodejs的dns解析模块是dns.js,下面是一个使用的例子。dns.lookup('www.a.com', function(err, address, family) { console.log(address);});我们根据沿着这个例子的代码看一下nodejs的dns过程。我们先看一下dns.js里的lookup函数,下面是核心代码。 var req = new Get...原创 2019-03-09 19:14:17 · 678 阅读 · 0 评论 -
nodejs之next_tick源码分析
next_tick函数是process对象的一个属性。他是在bootstrap_node.js中设置的。bootstrap_node.js NativeModule.require('internal/process/next_tick').setup();internal/process/next_tick process.nextTick = nextTick; functio...原创 2019-03-14 04:15:03 · 653 阅读 · 0 评论 -
nodejs之setImmediate源码分析
setImmediate函数的代码在lib/timer.js。function setImmediate(callback, arg1, arg2, arg3) { if (typeof callback !== 'function') { throw new errors.TypeError('ERR_INVALID_CALLBACK'); } var i, args;...原创 2019-03-14 03:04:55 · 1119 阅读 · 0 评论 -
libuv之文件监听---fs-poll.c
#include "uv.h"#include "uv-common.h"#include <assert.h>#include <stdlib.h>#include <string.h>struct poll_ctx { uv_fs_poll_t* parent_handle; /* NULL if parent has been sto...原创 2018-12-08 03:02:25 · 762 阅读 · 0 评论 -
libuv之定时器---timer.c
#include "uv.h"#include "uv-common.h"#include "heap-inl.h"#include <assert.h>#include <limits.h>// 取出loop中的计时器堆指针static struct heap *timer_heap(const uv_loop_t* loop) {#ifdef _W...原创 2018-12-08 00:35:44 · 1173 阅读 · 0 评论 -
libuv的定时器原理源码解析
首先我们看一下timer的结构体struct uv_timer_s { void* data; uv_loop_t* loop; uv_handle_type type; uv_close_cb close_cb; void* handle_queue[2]; union { int fd; voi...原创 2019-03-10 00:38:03 · 1025 阅读 · 2 评论 -
nodejs之setTimeout源码解析
setTimeout是在系统启动的时候挂载的全局函数。代码在timer.js。function setupGlobalTimeouts() { const timers = NativeModule.require('timers'); global.clearImmediate = timers.clearImmediate; global.clearInterval ...原创 2019-03-10 01:31:55 · 2349 阅读 · 0 评论 -
libuv之async.c源码解析
libuv的async.c实现了线程和主线程的通信。在uv_loop_init函数中对async进行初始化。 uv_async_init(loop, &loop->wq_async, uv__work_done); int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { i...原创 2019-03-10 05:51:28 · 647 阅读 · 0 评论 -
libuv之线程池以及线程间通信源码解析
libuv实现了一个线程池,该线程池在用户提交了第一个任务的时候初始化,而不是系统启动的时候就初始化。入口代码如下。static void init_once(void) {#ifndef _WIN32 /* Re-initialize the threadpool after fork. * Note that this discards the global mutex and ...原创 2019-03-10 06:32:01 · 938 阅读 · 2 评论 -
nodejs的http.createServer过程解析
下面是nodejs创建一个服务器的代码。接下来我们一起分析这个过程。var http = require('http');http.createServer(function (request, response) { response.end('Hello World\n');}).listen(9297);首先我们去到lib/http.js模块看一下这个函数的代码。functio...原创 2019-03-11 00:51:25 · 7981 阅读 · 0 评论 -
nodejs解析http协议源码解析
上篇文章讲到nodejs创建一个服务并且建立tcp连接的过程。接下来分析一下,在建立tcp连接后,nodejs是如何解析http协议的。我们首先看一下nodejs在建立tcp连接时执行net.js层的回调时做了什么操作。下面是核心代码。// clientHandle代表一个和客户端建立tcp连接的实体function onconnection(err, clientHandle) { va...原创 2019-03-12 02:40:13 · 1518 阅读 · 0 评论 -
nodejs之启动源码浅析
int main(int argc, char *argv[]) {#if defined(__linux__) char** envp = environ; while (*envp++ != nullptr) {} Elf_auxv_t* auxv = reinterpret_cast&lt;Elf_auxv_t*&gt;(envp); for (; auxv-&gt;a_t...原创 2019-03-16 18:26:27 · 1165 阅读 · 0 评论 -
nodejs之模块系统源码分析(上)
nodejs的模块分为几种,有内置的c++模块,内置的js模块,还有用户自定义的模块。下面我们先分析内置模块。然后在分析用户定义的模块。1 内置模块首先以注册tcp_wrap.cc模块为例子,一步步分析一下c++模块的注册。下面是tcp_wrap.cc模块的最后一句代码。 1 NODE_BUILTIN_MODULE_CONTEXT_AWARE(tcp_wrap, node::TCPWrap...原创 2019-03-17 00:56:48 · 956 阅读 · 2 评论 -
libuv之idle、check、prepare---loop-watcher.c
#include "uv.h"#include "internal.h"#define UV_LOOP_WATCHER_DEFINE(name, type) \ int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) { \...原创 2018-12-07 23:50:34 · 740 阅读 · 0 评论