[libuv] libuv学习
From: https://www.mobibrw.com/2016/3490
libuv 是重写了下libev,封装了windows和unix的差异性。
libuv的特点
非阻塞TCP套接字 socket?
非阻塞命名管道
UDP
定时器
子进程 fork?
通过 uv_getaddrinfo实现异步DNS
异步文件系统API uv_fs_*
高分辨率时间 uv_hrtime
正在运行程序路径查找 uv_exepath
线程池调度 uv_queue_work
TTY控制的ANSI转义代码 uv_tty_t
文件系统事件支持 inotify ReadDirectoryChangesW kqueue 马上回支持 uv_fs_event_t
进程间的IPC与套接字共享 uv_write2
事件驱动的风格:程序关注/发送事件,在事件来临时给出反应。
系统编程中,一般都是在处理I/O,而IO的主要障碍是网络读取,在读取的时候是阻塞掉的。标准的解决方案是使用多线程,每一个阻塞的IO操作被分配到一个线程。当线程block,处理器调度处理其他线程。
libuv使用了另一个方案,异步。操作系统提供了socket的事件,即使用socket,监听socket事件即可。
libuv简单使用 创建一个loop,关闭loop。
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>
int main()
{
uv_loop_t *loop = malloc(sizeof(uv_loop_t));
uv_loop_init(loop);
printf("hello, libuv");
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_close(loop);
free(loop);
return 0;
}
如果只需要一个loop的话,调用uv_default_loop就可以了。
tips:Nodejs中使用了这个loop作为主loop。
uv_loop_t *loop = uv_default_loop();
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_close(loop);
Error
初始化或同步函数,会在执行失败是返回一个负数,可以通过uv_strerror、uv_err_name获得这个错误的名字和含义
I/O函数的回调函数会被传递一个nread参数,如果nread小于0,也代表出现了错误。
Handle & Request
libuv的工作建立在事件的监听上,通常通过handle来实现,handle中uv_TYPE_t中的type指定了handle监听的事件。
在uv.h中可以找到handle和request的定义
/* Handle types. */
typedef struct uv_loop_s uv_loop_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t;
typedef struct uv_pipe_s uv_pipe_t;
typedef struct uv_tty_s uv_tty_t;
typedef struct uv_poll_s uv_poll_t;
typedef struct uv_timer_s uv_timer_t;
typedef struct uv_prepare_s uv_prepare_t;
typedef struct uv_check_s uv_check_t;
typedef struct uv_idle_s uv_idle_t;
typedef struct uv_async_s uv_async_t;
typedef struct uv_process_s uv_process_t;
typedef struct uv_fs_event_s uv_fs_event_t;
typedef struct uv_fs_poll_s uv_fs_poll_t;
typedef struct uv_signal_s uv_signal_t;
/* Request types. */
typedef struct uv_req_s uv_req_t;
typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
typedef struct uv_getnameinfo_s uv_getnameinfo_t;
typedef struct uv_shutdown_s uv_shutdown_t;
typedef struct uv_write_s uv_write_t;
typedef struct uv_connect_s uv_connect_t;
typedef struct uv_udp_send_s uv_udp_send_t;
typedef struct uv_fs_s uv_fs_t;
typedef struct uv_work_s uv_work_t;
/* None of the above. */
typedef struct uv_cpu_info_s uv_cpu_info_t;
typedef struct uv_interface_address_s uv_interface_address_t;
typedef struct uv_dirent_s uv_dirent_t;
handle是持久化的对象。在异步操作中,相应的handle有许多关联的request。
request是短暂性的,通常只维持一个回调的时间,一般对应handle的一个IO操作。request用来在初始函数和回调函数中传递上下文。
例如uv_udp_t代表了一个udp的socket,每一个socket的写入完成后,都有一个uv_udp_send_t被传递。
handle的设置
uv_TYPE_init(uv_loop_t*, uv_TYPE_t);
一个idle handle的使用例子 观察下它的生命周期
#include <stdio.h>
#include <uv.h>
int counter = 0;
void wait_for(uv_idle_t * handle)
{
counter++;
if (counter > 10e6)
{
uv_idle_stop(handle);
}
}
int main()
{
uv_idle_t idler;
uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for);
printf("Idle......");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
return 0;
}
参数传递
handle和request都有一个data域,用来传递信息。uv_loop_t也有一个相似的data域。
文件系统
简单的文件读写是通过uv_fs_*函数族和与之相关的uv_fs_t结构体完成的。
系统的文件操作是阻塞的,所以libuv在线程池中调用这些函数,最后通知loop。
如果没有指定回调函数,文件操作是同步的,return libuv error code。
异步在传入回调函数时调用,return 0。
获得文件描述符
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb);
关闭文件描述符
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
回调函数
void callback(uv_fs_t* req);
还有uv_fs_read uv_fs_write uv_fs_t构成了基本的文件操作
流操作使用uv_stream_t,比基本操作方便不少
uv_read_start uv_read_stop uv_write
流操作可以很好的配合pipe使用
pipe相关函数
uv_pipe_init uv_pipe_open uv_close
文件事件
uv_fs_event_t uv_fs_event_init uv_fs_event_start
网络
uv_ip4_addr ip为 0.0.0.0表示绑定所有接口 255.255.255.255是一个广播地址,意味着数据将往所有的子网接口发送,端口号0表示由操作系统随机分配一个端口
tcp
TCP是面向连接的字节流协议,因此基于libuv的stream实现
uv_tcp_t
服务器端创建流程
uv_tcp_init 建立tcp句柄
uv_tcp_bind 绑定
uv_listen 建立监听,当有新的连接到来时,激活调用回调函数
uv_accept 接收链接
使用stream处理数据以及与客户端通信
客户端
客户端比较简单,只需要调用uv_tcp_connect
udp
UDP是不可靠连接,libuv基于uv_udp_t和uv_udp_send_t
udp的流程与tcp类似
libuv提供了一个异步的DNS解决方案,提供了自己的getaddrinfo
配置好主机参数addrinfo后使用uv_getaddrinfo即可
调用uv_interface_addresses获得系统的网络信息
未完待续。
来源:http://luohaha.github.io/Chinese-uvbook/source/introduction.html
[libuv] libuv学习相关推荐
- linux libuv,libuv queue的实现
最近看node源码的时候注意到libuv中的一个队列实现,是c风格的,也是linux内核中常见的写法,因为一直使用c++的队列,所以对这种写法看不太懂,经过向牛人请教,终于明白了其中奥妙. 先一窥芳容 ...
- [libuv] libuv安装
环境: centos7.2, gcc,g++ version: 4.8.5 yum install -y libuv libuv-devel
- 【libuv高效编程】libuv学习超详细教程1——libuv的编译与安装
文章目录 libuv简介 下载libuv 安装必要的依赖 拉取libuv源码 编译使用 验证编译安装是否完成 简单实用 libuv简介 libuv 是一个高性能的,事件驱动的I/O,并且支持多平台的网 ...
- linux下编译libuv,linux下libuv库安装教程
下载并编译libuv libuv需要自己手动下载源码,并手动编译. 当前目录为:/home/xlz/test/github/,在后面,会用$PATH来代替,我的系统的Debian8,64bit. $g ...
- Libuv的安装及运行使用
Libuv的安装及运行使用 Libuv的官网链接:http://libuv.org/ GitHub下载链接:https://github.com/libuv/libuv CMake下载链接:https ...
- libuv 高性能 事件驱动 跨平台 i/o库 简介
目录 1.Introduction 简介 Who this book is for Background Code 2.Basics of libuv libuv基础 Event loops HELL ...
- linux libuv 交叉编译 高性能事件驱动库
1.由于需要热插拔功能,所以 libuv 需要链接 udev 库,下面是 eudev 的交叉编译 eudev 下载地址:https://github.com/gentoo/eudev 解压,执行: . ...
- [Nodejs原理] 核心库Libuv入门(Hello World篇)
Libuv是什么? 1. 简介 Libuv是一个高性能的,事件驱动的异步I/O库,它本身是由C语言编写的,具有很高的可移植性.libuv封装了不同平台底层对于异步IO模型的实现,所以它还本身具备着Wi ...
- libuv udp server和client
libuv libuv是nodejs异步的io库,并非仅仅是网络,还包括文件,我们使用该库的异步通信机制来制作udp的server和client. 在windows平台上要包含一些lib 1 发送方 ...
最新文章
- svn“Previous operation has not finished; run 'cleanup' if it was interrupted“报错的解决方法
- 最好用的 IntelliJ 插件 Top 10
- Java实体类对象修改日志记录
- python代码打开可执行文件_将自己的Python代码打包成exe文件(更换设备可运行的)...
- 好久没敲代码了(强行补上今天的博客。。。)
- 7-5 列车厢调度 (25 分)
- PTA12、 统计文字中的单词数量并按出现次数排序 (10 分)
- 分布式技术追踪 2018年第二期
- vue 项目难点_Vue 项目里戳中你痛点的问题及解决办法
- HTML知识积累及实践(四) - 表单元素
- 第10章 评价分类结果 学习笔记中
- 树莓派安装OpenCV2教程 (详细教程)
- python支持wps_Linux上使用python调用WPS二次开发接口
- origin作功率谱图
- 小招喵喜欢吃喵粮(贪心、二分查找)
- 攻防世界 Reverse高手进阶区 2分题 reverse-for-the-holy-grail-350
- iphone7刷入linux,iPhone7怎么进入DFU模式 iPhone7刷机步骤【详解】
- linux下解压iso镜像文件方法
- R语言使用cph函数和rcs函数构建限制性立方样条cox回归模型、检验模型是否满足等比例风险、是否存在非线性关系、使用rms包的Predict函数计算指定连续变量和风险比HR值的关系并可视化
- B站 马士兵Python 入门基础版 - 课程笔记
热门文章
- eclipse4.3.1标准版安装freemarker插件
- 中小企业如何提高售前,售中,售后客服质量?
- 艾伟:ASP.NET跨页面传值技巧总结
- 讯闪菜单密码去除方法
- 旧金山字体_旧金山建筑业的兴衰。 施工趋势与历史
- 编写程序乘法口诀表C语言,陈广川问:c语言编程九九乘法口诀表 怎样用c语言写九九乘法口诀表?...
- linux中gradle编译慢,【Linux】解决linux下android studio用gradle构建从jcenter或maven下载依赖太慢...
- leetcode950. 按递增顺序显示卡牌
- react 图像识别_无法在React中基于URL查找图像
- 在ASP.NET Atlas中调用Web Service——创建Mashup调用远端Web Service(基础知识以及简单示例)...