当前位置: 首页 > news >正文

libuv 框架

概述

libuv 是一个跨平台的异步 I/O 库,最初为 Node.js 开发,现在也被 Luvit、Julia 和其他项目使用。它提供了一套高性能的事件驱动编程模型,抽象了不同操作系统上的非阻塞 I/O 操作,并提供了统一的 API。

主要特性

  • 完整的事件循环:基于 epoll、kqueue、IOCP、event ports 等机制

  • 异步 TCP 和 UDP 套接字

  • 异步 DNS 解析

  • 异步文件和文件系统操作

  • 文件系统事件

  • ANSI 转义控制的 TTY

  • 进程间通信:支持通过 Unix domain sockets 或命名管道共享套接字

  • 子进程管理

  • 线程池

  • 信号处理

  • 高精度时钟

  • 线程和同步原语

核心概念

1. 事件循环 (Event Loop)

事件循环是 libuv 的核心,所有的 I/O 操作都在事件循环中进行。它通过以下接口管理:

  • uv_loop_t:表示事件循环的结构体

  • uv_loop_init():初始化事件循环

  • uv_run():启动事件循环

  • uv_loop_close():关闭事件循环

2. 句柄 (Handle)

句柄是 libuv 中长期存在的对象,通常用于表示资源。所有的句柄都继承自 uv_handle_t

  • uv_tcp_t:TCP 套接字

  • uv_udp_t:UDP 套接字

  • uv_pipe_t:命名管道

  • uv_tty_t:终端 I/O

  • uv_poll_t:文件描述符轮询

  • uv_timer_t:定时器

  • uv_prepare_tuv_check_tuv_idle_t:事件循环阶段回调

  • uv_async_t:异步回调触发器

  • uv_process_t:子进程

  • uv_fs_event_t:文件系统事件

  • uv_fs_poll_t:文件系统轮询

3. 请求 (Request)

请求是短期存在的对象,表示一次操作。所有的请求都继承自 uv_req_t

  • uv_write_t:写请求

  • uv_connect_t:连接请求

  • uv_shutdown_t:关闭请求

  • uv_udp_send_t:UDP 发送请求

  • uv_fs_t:文件系统请求

  • uv_getaddrinfo_t:DNS 解析请求

  • uv_getnameinfo_t:反向 DNS 解析请求

  • uv_work_t:线程池工作请求

  • uv_random_t:随机数生成请求

4. 回调机制

libuv 使用回调来处理异步操作的结果。通常所有异步函数都接受一个回调函数作为最后一个参数:

uv_fs_open(loop, &req, "file.txt", O_RDONLY, 0, on_open);void on_open(uv_fs_t* req) {// 处理打开文件的结果
}

主要模块

1. 网络操作

libuv 提供了完整的网络编程接口:

  • TCP:提供流式的、可靠的双向通信通道

    • uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle)

      • 功能:初始化TCP句柄

      • 参数:

        • loop:事件循环

        • handle:TCP句柄指针

      • 返回值:成功返回0,失败返回错误码

    • uv_tcp_bind(uv_tcp_t* handle, const struct sockaddr* addr, unsigned int flags)

      • 功能:将句柄绑定到特定的地址和端口

      • 参数:

        • handle:TCP句柄指针

        • addr:要绑定的地址结构体

        • flags:额外的标志,如UV_TCP_IPV6ONLY

      • 返回值:成功返回0,失败返回错误码

    • uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb)

      • 功能:在指定的流上开始监听连接

      • 参数:

        • stream:流句柄(TCP、管道等)

        • backlog:连接队列大小

        • cb:新连接到达时的回调函数

      • 返回值:成功返回0,失败返回错误码

      • 回调签名:void (*uv_connection_cb)(uv_stream_t* server, int status)

    • uv_accept(uv_stream_t* server, uv_stream_t* client)

      • 功能:接受传入的连接

      • 参数:

        • server:监听连接的服务器句柄

        • client:接受连接的客户端句柄

      • 返回值:成功返回0,失败返回错误码

    • uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, const struct sockaddr* addr, uv_connect_cb cb)

      • 功能:建立到目标地址的TCP连接

      • 参数:

        • req:连接请求句柄

        • handle:TCP句柄

        • addr:目标地址

        • cb:连接完成时的回调函数

      • 返回值:成功返回0,失败返回错误码

      • 回调签名:void (*uv_connect_cb)(uv_connect_t* req, int status)

示例:创建 TCP 服务器

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>uv_loop_t* loop;
struct sockaddr_in addr;void on_connection(uv_stream_t* server, int status) {if (status < 0) {fprintf(stderr, "连接错误 %s\n", uv_strerror(status));return;}uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));uv_tcp_init(loop, client);if (uv_accept(server, (uv_stream_t*)client) == 0) {// 处理新客户端连接printf("新客户端已连接\n");} else {uv_close((uv_handle_t*)client, NULL);free(client);}
}int main() {loop = uv_default_loop();uv_tcp_t server;uv_tcp_init(loop, &server);uv_ip4_addr("0.0.0.0", 8080, &addr);uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);int r = uv_listen((uv_stream_t*)&server, 128, on_connection);if (r) {fprintf(stderr, "监听错误 %s\n", uv_strerror(r));return 1;}return uv_run(loop, UV_RUN_DEFAULT);
}

  • UDP:提供无连接的消息通信

    • uv_udp_init(uv_loop_t* loop, uv_udp_t* handle)

      • 功能:初始化UDP句柄

      • 参数:

        • loop:事件循环

        • handle:UDP句柄指针

      • 返回值:成功返回0,失败返回错误码

    • uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int flags)

      • 功能:将句柄绑定到特定的地址和端口

      • 参数:

        • handle:UDP句柄指针

        • addr:要绑定的地址结构体

        • flags:标志位,例如:

          • UV_UDP_IPV6ONLY:仅使用IPv6

          • UV_UDP_REUSEADDR:允许地址重用

      • 返回值:成功返回0,失败返回错误码

    • uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, const uv_buf_t bufs[ ], unsigned int nbufs, const struct sockaddr* addr, uv_udp_send_cb send_cb)

      • 功能:发送UDP数据包

      • 参数:

        • req:发送请求句柄

        • handle:UDP句柄

        • bufs:包含数据的缓冲区数组

        • nbufs:缓冲区数组中的元素数量

        • addr:目标地址

        • send_cb:发送完成时的回调函数

      • 返回值:成功返回0,失败返回错误码

      • 回调签名:void (*uv_udp_send_cb)(uv_udp_send_t* req, int status)

    • uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb)

      • 功能:开始接收UDP数据包

      • 参数:

        • handle:UDP句柄

        • alloc_cb:分配接收缓冲区的回调函数

        • recv_cb:接收到数据包时的回调函数

      • 返回值:成功返回0,失败返回错误码

      • 回调签名:

        • void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)

        • void (*uv_udp_recv_cb)(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags)

    • uv_udp_recv_stop(uv_udp_t* handle)

      • 功能:停止接收UDP数据包

      • 参数:

        • handle:UDP句柄

      • 返回值:成功返回0,失败返回错误码

示例:UDP 服务器

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>uv_loop_t* loop;
uv_udp_t recv_socket;
struct sockaddr_in addr;void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {buf->base = (char*)malloc(suggested_size);buf->len = suggested_size;
}void on_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf,const struct sockaddr* addr, unsigned flags) {if (nread > 0) {char sender[17] = {0};uv_ip4_name((const struct sockaddr_in*)addr, sender, 16);printf("收到来自 %s 的消息: %.*s\n", sender, (int)nread, buf->base);}free(buf->base);
}int main() {loop = uv_default_loop();uv_udp_init(loop, &recv_socket);uv_ip4_addr("0.0.0.0", 9000, &addr);uv_udp_bind(&recv_socket, (const struct sockaddr*)&addr, 0);uv_udp_recv_start(&recv_socket, alloc_buffer, on_recv);return uv_run(loop, UV_RUN_DEFAULT);
}

  • DNS:提供异步 DNS 解析

    • uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints)

      • 功能:异步DNS解析,将主机名转换为地址

      • 参数:

        • loop:事件循环

        • req:DNS解析请求句柄

        • getaddrinfo_cb:解析完成时的回调函数

        • node:要解析的主机名(如"www.example.com"),或IP地址

        • service:服务名或端口号(如"http"或"80")

        • hints:控制解析过程的选项,包括地址族、套接字类型等

      • 返回值:成功返回0,失败返回错误码

      • 回调签名:void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, int status, struct addrinfo* res)

    • uv_getnameinfo(uv_loop_t* loop, uv_getnameinfo_t* req, uv_getnameinfo_cb getnameinfo_cb, const struct sockaddr* addr, int flags)

      • 功能:异步反向DNS解析,将地址转换为主机名

      • 参数:

        • loop:事件循环

        • req:请求句柄

        • getnameinfo_cb:解析完成时的回调函数

        • addr:要解析的IP地址

        • flags:控制解析过程的标志,如NI_NAMEREQD、NI_NUMERICHOST等

      • 返回值:成功返回0,失败返回错误码

      • 回调签名:void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, int status, const char* hostname, const char* service)

    • uv_freeaddrinfo(struct addrinfo* ai)

      • 功能:释放由uv_getaddrinfo分配的地址信息资源

      • 参数:

        • ai:要释放的addrinfo结构体

      • 返回值:无

示例:DNS 解析

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>uv_loop_t* loop;void on_resolved(uv_getaddrinfo_t* resolver, int status, struct addrinfo* res) {if (status < 0) {fprintf(stderr, "解析错误 %s\n", uv_strerror(status));return;}char addr[17] = {0};uv_ip4_name((struct sockaddr_in*)res->ai_addr, addr, 16);printf("域名解析结果: %s\n", addr);uv_freeaddrinfo(res);free(resolver);
}int main() {loop = uv_default_loop();struct addrinfo hints;memset(&hints, 0, sizeof(hints));hints.ai_family = AF_INET;hints.ai_socktype = SOCK_STREAM;uv_getaddrinfo_t* resolver = (uv_getaddrinfo_t*)malloc(sizeof(uv_getaddrinfo_t));int r = uv_getaddrinfo(loop, resolver, on_resolved, "www.example.com", "80", &hints);if (r) {fprintf(stderr, "解析请求错误 %s\n", uv_strerror(r));return 1;}return uv_run(loop, UV_RUN_DEFAULT);
}

2. 文件系统

提供异步文件 I/O 操作:

  • uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb)

    • 功能:异步打开文件

    • 参数:

      • loop:事件循环

      • req:文件系统请求句柄

      • path:要打开的文件路径

      • flags:打开模式,如O_RDONLY、O_WRONLY、O_CREAT等

      • mode:文件权限,如S_IRUSR、S_IWUSR等(创建文件时使用)

      • cb:操作完成时的回调函数,若为NULL则为同步调用

    • 返回值:同步模式下返回文件描述符或错误码,异步模式下成功返回0,错误返回错误码

    • 回调签名:void (*uv_fs_cb)(uv_fs_t* req)

  • uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[ ], unsigned int nbufs, int64_t offset, uv_fs_cb cb)

    • 功能:异步读取文件内容

    • 参数:

      • loop:事件循环

      • req:文件系统请求句柄

      • file:文件描述符

      • bufs:缓冲区数组,用于存储读取的数据

      • nbufs:缓冲区数组中的元素数量

      • offset:从文件的哪个位置开始读取,如为-1则从当前位置开始

      • cb:操作完成时的回调函数

    • 返回值:同步模式下返回读取的字节数或错误码,异步模式下成功返回0,错误返回错误码

    • 回调访问结果:req->result 包含读取的字节数

  • uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[ ], unsigned int nbufs, int64_t offset, uv_fs_cb cb)

    • 功能:异步写入文件内容

    • 参数:

      • loop:事件循环

      • req:文件系统请求句柄

      • file:文件描述符

      • bufs:包含要写入数据的缓冲区数组

      • nbufs:缓冲区数组中的元素数量

      • offset:在文件的哪个位置开始写入,如为-1则从当前位置开始

      • cb:操作完成时的回调函数

    • 返回值:同步模式下返回写入的字节数或错误码,异步模式下成功返回0,错误返回错误码

    • 回调访问结果:req->result 包含写入的字节数

  • uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)

    • 功能:异步关闭文件

    • 参数:

      • loop:事件循环

      • req:文件系统请求句柄

      • file:要关闭的文件描述符

      • cb:操作完成时的回调函数

    • 返回值:同步模式下成功返回0,错误返回错误码,异步模式下成功返回0,错误返回错误码

  • uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)

    • 功能:异步删除文件

    • 参数:

      • loop:事件循环

      • req:文件系统请求句柄

      • path:要删除的文件路径

      • cb:操作完成时的回调函数

    • 返回值:同步模式下成功返回0,错误返回错误码,异步模式下成功返回0,错误返回错误码

  • uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)

    • 功能:异步创建目录

    • 参数:

      • loop:事件循环

      • req:文件系统请求句柄

      • path:要创建的目录路径

      • mode:目录权限

      • cb:操作完成时的回调函数

    • 返回值:同步模式下成功返回0,错误返回错误码,异步模式下成功返回0,错误返回错误码

  • uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)

    • 功能:异步获取文件状态

    • 参数:

      • loop:事件循环

      • req:文件系统请求句柄

      • path:要查询的文件或目录路径

      • cb:操作完成时的回调函数

    • 返回值:同步模式下成功返回0,错误返回错误码,异步模式下成功返回0,错误返回错误码

    • 回调访问结果:req->statbuf 包含文件状态信息

示例:异步读取文件

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>uv_loop_t* loop;
uv_fs_t open_req;
uv_fs_t read_req;
uv_fs_t close_req;
char buffer[1024];void on_read(uv_fs_t* req);void on_open(uv_fs_t* req) {if (req->result < 0) {fprintf(stderr, "打开文件错误: %s\n", uv_strerror(req->result));return;}// 文件打开成功,开始读取uv_buf_t buf = uv_buf_init(buffer, sizeof(buffer));uv_fs_read(loop, &read_req, req->result, &buf, 1, 0, on_read);
}void on_read(uv_fs_t* req) {if (req->result < 0) {fprintf(stderr, "读取错误: %s\n", uv_strerror(req->result));} else if (req->result == 0) {// 已读到文件末尾,关闭文件uv_fs_close(loop, &close_req, open_req.result, NULL);} else {// 成功读取一些数据printf("读取了 %ld 字节: %.*s\n", req->result, (int)req->result, buffer);// 继续读取更多内容uv_buf_t buf = uv_buf_init(buffer, sizeof(buffer));uv_fs_read(loop, &read_req, open_req.result, &buf, 1, req->off + req->result, on_read);}
}int main() {loop = uv_default_loop();// 异步打开文件uv_fs_open(loop, &open_req, "example.txt", O_RDONLY, 0, on_open);return uv_run(loop, UV_RUN_DEFAULT);
}

3. 线程操作

提供线程创建和同步操作:

  • uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg)

    • 功能:创建新线程

    • 参数:

      • tid:线程标识符,用于存储新创建的线程ID

      • entry:线程入口函数

      • arg:传递给线程入口函数的参数

    • 返回值:成功返回0,失败返回错误码

    • 回调签名:void (*uv_thread_cb)(void* arg)

  • uv_thread_join(uv_thread_t* tid)

    • 功能:等待指定线程结束

    • 参数:

      • tid:要等待的线程标识符

    • 返回值:成功返回0,失败返回错误码

  • uv_mutex_init(uv_mutex_t* mutex)

    • 功能:初始化互斥锁

    • 参数:

      • mutex:互斥锁指针

    • 返回值:成功返回0,失败返回错误码

  • uv_mutex_lock(uv_mutex_t* mutex)

    • 功能:锁定互斥锁

    • 参数:

      • mutex:要锁定的互斥锁

    • 返回值:成功返回0,失败返回错误码

  • uv_mutex_unlock(uv_mutex_t* mutex)

    • 功能:解锁互斥锁

    • 参数:

      • mutex:要解锁的互斥锁

    • 返回值:成功返回0,失败返回错误码

  • uv_mutex_destroy(uv_mutex_t* mutex)

    • 功能:销毁互斥锁

    • 参数:

      • mutex:要销毁的互斥锁

    • 返回值:成功返回0,失败返回错误码

  • uv_sem_init(uv_sem_t* sem, unsigned int value)

    • 功能:初始化信号量

    • 参数:

      • sem:信号量指针

      • value:信号量的初始值

    • 返回值:成功返回0,失败返回错误码

  • uv_sem_post(uv_sem_t* sem)

    • 功能:增加信号量的值

    • 参数:

      • sem:信号量指针

    • 返回值:成功返回0,失败返回错误码

  • uv_sem_wait(uv_sem_t* sem)

    • 功能:减少信号量的值,如果信号量为0则阻塞

    • 参数:

      • sem:信号量指针

    • 返回值:成功返回0,失败返回错误码

  • uv_sem_destroy(uv_sem_t* sem)

    • 功能:销毁信号量

    • 参数:

      • sem:要销毁的信号量

    • 返回值:成功返回0,失败返回错误码

  • uv_cond_init(uv_cond_t* cond)

    • 功能:初始化条件变量

    • 参数:

      • cond:条件变量指针

    • 返回值:成功返回0,失败返回错误码

  • uv_cond_signal(uv_cond_t* cond)

    • 功能:唤醒等待条件变量的单个线程

    • 参数:

      • cond:条件变量指针

    • 返回值:成功返回0,失败返回错误码

  • uv_cond_broadcast(uv_cond_t* cond)

    • 功能:唤醒所有等待条件变量的线程

    • 参数:

      • cond:条件变量指针

    • 返回值:成功返回0,失败返回错误码

  • uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex)

    • 功能:等待条件变量被触发

    • 参数:

      • cond:条件变量指针

      • mutex:与条件变量关联的互斥锁

    • 返回值:成功返回0,失败返回错误码

  • uv_cond_destroy(uv_cond_t* cond)

    • 功能:销毁条件变量

    • 参数:

      • cond:要销毁的条件变量

    • 返回值:成功返回0,失败返回错误码

  • uv_barrier_init(uv_barrier_t* barrier, unsigned int count)

    • 功能:初始化屏障

    • 参数:

      • barrier:屏障指针

      • count:需要等待的线程数量

    • 返回值:成功返回0,失败返回错误码

  • uv_barrier_wait(uv_barrier_t* barrier)

    • 功能:在屏障处等待,直到所有线程都到达屏障

    • 参数:

      • barrier:屏障指针

    • 返回值:成功时,其中一个线程返回非零值,其他线程返回0;失败返回错误码

  • uv_barrier_destroy(uv_barrier_t* barrier)

    • 功能:销毁屏障

    • 参数:

      • barrier:要销毁的屏障

    • 返回值:成功返回0,失败返回错误码

示例:使用线程和互斥锁

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>#define THREAD_COUNT 5uv_mutex_t mutex;
int counter = 0;void thread_entry(void* arg) {int thread_id = *(int*)arg;// 使用互斥锁保护共享变量uv_mutex_lock(&mutex);counter++;printf("线程 %d: 计数器现在是 %d\n", thread_id, counter);uv_mutex_unlock(&mutex);free(arg);
}int main() {uv_thread_t threads[THREAD_COUNT];// 初始化互斥锁uv_mutex_init(&mutex);// 创建多个线程for (int i = 0; i < THREAD_COUNT; i++) {int* thread_id = (int*)malloc(sizeof(int));*thread_id = i;uv_thread_create(&threads[i], thread_entry, thread_id);}// 等待所有线程结束for (int i = 0; i < THREAD_COUNT; i++) {uv_thread_join(&threads[i]);}// 销毁互斥锁uv_mutex_destroy(&mutex);printf("最终计数器值: %d\n", counter);return 0;
}

4. 进程管理

提供子进程的创建和管理:

  • uv_spawn(uv_loop_t* loop, uv_process_t* handle, const uv_process_options_t* options)

    • 功能:创建子进程

    • 参数:

      • loop:事件循环

      • handle:进程句柄

      • options:进程选项,包括:

        • exit_cb:子进程退出时的回调函数

        • file:可执行文件路径

        • args:命令行参数数组

        • env:环境变量

        • cwd:工作目录

        • flags:进程标志,如UV_PROCESS_DETACHED

        • stdio_countstdio:标准输入输出重定向

        • uidgid:子进程的用户和组ID

    • 返回值:成功返回0,失败返回错误码

    • 回调签名:void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal)

  • uv_process_kill(uv_process_t* handle, int signum)

    • 功能:向子进程发送信号

    • 参数:

      • handle:进程句柄

      • signum:要发送的信号编号,如SIGTERM、SIGKILL等

    • 返回值:成功返回0,失败返回错误码

  • uv_kill(int pid, int signum)

    • 功能:向指定PID的进程发送信号

    • 参数:

      • pid:目标进程的PID

      • signum:要发送的信号编号

    • 返回值:成功返回0,失败返回错误码

  • uv_process_get_pid(const uv_process_t* handle)

    • 功能:获取子进程的PID

    • 参数:

      • handle:进程句柄

    • 返回值:子进程的PID

示例:创建子进程

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>uv_loop_t* loop;
uv_process_t child_req;
uv_process_options_t options;void on_process_exit(uv_process_t* req, int64_t exit_status, int term_signal) {printf("子进程退出,状态码: %lld, 信号: %d\n", exit_status, term_signal);uv_close((uv_handle_t*)req, NULL);
}int main() {loop = uv_default_loop();// 设置子进程的标准输入输出uv_stdio_container_t stdio[3];stdio[0].flags = UV_IGNORE;        // 忽略标准输入stdio[1].flags = UV_INHERIT_FD;    // 继承父进程的标准输出stdio[1].data.fd = 1;stdio[2].flags = UV_INHERIT_FD;    // 继承父进程的标准错误stdio[2].data.fd = 2;// 初始化选项memset(&options, 0, sizeof(options));options.exit_cb = on_process_exit;options.file = "/bin/hello";options.args = (char*[]){"/bin/hello", NULL};  // 需要设置参数数组options.flags = 0;options.stdio = stdio;options.stdio_count = 3;int r = uv_spawn(loop, &child_req, &options);if (r) {fprintf(stderr, "生成子进程错误 %s\n", uv_strerror(r));return 1;} else {printf("启动了 PID %d 的进程\n", child_req.pid);}return uv_run(loop, UV_RUN_DEFAULT);
}

5. 定时器和事件

  • uv_timer_init(uv_loop_t* loop, uv_timer_t* handle)

    • 功能:初始化定时器句柄

    • 参数:

      • loop:事件循环

      • handle:定时器句柄指针

    • 返回值:成功返回0,失败返回错误码

  • uv_timer_start(uv_timer_t* handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat)

    • 功能:启动定时器

    • 参数:

      • handle:定时器句柄

      • cb:定时器到期时的回调函数

      • timeout:首次触发的延迟时间(毫秒)

      • repeat:重复间隔(毫秒),0表示不重复

    • 返回值:成功返回0,失败返回错误码

    • 回调签名:void (*uv_timer_cb)(uv_timer_t* handle)

  • uv_timer_stop(uv_timer_t* handle)

    • 功能:停止定时器

    • 参数:

      • handle:定时器句柄

    • 返回值:成功返回0,失败返回错误码

  • uv_timer_again(uv_timer_t* handle)

    • 功能:重新启动定时器

    • 参数:

      • handle:定时器句柄

    • 返回值:成功返回0,失败返回错误码

  • uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat)

    • 功能:设置定时器的重复间隔

    • 参数:

      • handle:定时器句柄

      • repeat:重复间隔(毫秒)

    • 返回值:无

  • uv_timer_get_repeat(const uv_timer_t* handle)

    • 功能:获取定时器的重复间隔

    • 参数:

      • handle:定时器句柄

    • 返回值:重复间隔(毫秒)

  • uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle)

    • 功能:初始化文件系统事件监视器

    • 参数:

      • loop:事件循环

      • handle:文件系统事件句柄指针

    • 返回值:成功返回0,失败返回错误码

  • uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags)

    • 功能:开始监视文件或目录的变化

    • 参数:

      • handle:文件系统事件句柄

      • cb:事件发生时的回调函数

      • path:要监视的文件或目录路径

      • flags:监视选项,可以是以下值的组合:

        • UV_FS_EVENT_WATCH_ENTRY:只监视目录条目本身的变化

        • UV_FS_EVENT_STAT:使用stat轮询来监视(网络文件系统)

        • UV_FS_EVENT_RECURSIVE:递归监视子目录

    • 返回值:成功返回0,失败返回错误码

    • 回调签名:void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status)

    • 事件类型:

      • UV_RENAME:文件被重命名

      • UV_CHANGE:文件内容或属性被修改

  • uv_fs_event_stop(uv_fs_event_t* handle)

    • 功能:停止监视文件系统事件

    • 参数:

      • handle:文件系统事件句柄

    • 返回值:成功返回0,失败返回错误码

  • uv_signal_init(uv_loop_t* loop, uv_signal_t* handle)

    • 功能:初始化信号处理器

    • 参数:

      • loop:事件循环

      • handle:信号句柄指针

    • 返回值:成功返回0,失败返回错误码

  • uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum)

    • 功能:开始监听特定信号

    • 参数:

      • handle:信号句柄

      • signal_cb:信号到达时的回调函数

      • signum:要监听的信号编号,如SIGINT、SIGTERM等

    • 返回值:成功返回0,失败返回错误码

    • 回调签名:void (*uv_signal_cb)(uv_signal_t* handle, int signum)

  • uv_signal_stop(uv_signal_t* handle)

    • 功能:停止监听信号

    • 参数:

      • handle:信号句柄

    • 返回值:成功返回0,失败返回错误码

示例:使用定时器

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>uv_loop_t* loop;
uv_timer_t timer;
int counter = 0;void timer_cb(uv_timer_t* handle) {counter++;printf("定时器回调: %d\n", counter);if (counter >= 5) {// 5次后停止定时器uv_timer_stop(handle);printf("定时器已停止\n");}
}int main() {loop = uv_default_loop();// 初始化定时器uv_timer_init(loop, &timer);// 启动定时器:1秒后开始,每隔1秒触发一次uv_timer_start(&timer, timer_cb, 1000, 1000);return uv_run(loop, UV_RUN_DEFAULT);
}

示例:文件系统事件监控(需要打开系统 FS_NOTIFY 功能)

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>uv_loop_t* loop;
uv_fs_event_t fs_event;void fs_event_cb(uv_fs_event_t* handle, const char* filename, int events, int status) {if (status < 0) {fprintf(stderr, "文件系统事件错误: %s\n", uv_strerror(status));return;}if (events & UV_RENAME) {printf("文件 %s 被重命名\n", filename ? filename : "未知");}if (events & UV_CHANGE) {printf("文件 %s 被修改\n", filename ? filename : "未知");}
}int main() {loop = uv_default_loop();// 初始化文件系统事件监控uv_fs_event_init(loop, &fs_event);// 开始监控目录int r = uv_fs_event_start(&fs_event, fs_event_cb, "/tmp", 0);if (r) {fprintf(stderr, "监控错误: %s\n", uv_strerror(r));return 1;}return uv_run(loop, UV_RUN_DEFAULT);
}

示例:信号处理

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>uv_loop_t* loop;
uv_signal_t sig_int;
uv_signal_t sig_term;void signal_handler(uv_signal_t* handle, int signum) {printf("收到信号: %d (%s)\n", signum, signum == SIGINT ? "SIGINT" : "SIGTERM");// 处理完后停止监听uv_signal_stop(handle);// 如果所有信号处理器都停止了,就可以退出循环if (!uv_is_active((uv_handle_t*)&sig_int) && !uv_is_active((uv_handle_t*)&sig_term)) {printf("所有信号处理器都已停止,退出中...\n");uv_stop(loop);}
}int main() {loop = uv_default_loop();// 初始化信号处理器uv_signal_init(loop, &sig_int);uv_signal_init(loop, &sig_term);// 开始监听 SIGINT 和 SIGTERM 信号uv_signal_start(&sig_int, signal_handler, SIGINT);uv_signal_start(&sig_term, signal_handler, SIGTERM);printf("按 Ctrl+C 发送 SIGINT 信号\n");return uv_run(loop, UV_RUN_DEFAULT);
}

NuttX 与 libuv 集成

在 NuttX 系统中,libuv 通过适配层集成,主要实现在 nuttx.c 文件中,提供了以下功能:

  • 针对 NuttX 的事件循环实现

  • 文件系统操作的适配

  • 网络功能的适配

  • 进程和线程功能的适配

结论

libuv 提供了高性能、跨平台的异步 I/O 能力,是构建高性能网络服务和应用程序的理想框架。它的事件驱动模型和统一的 API 使得开发者能够更容易地编写高效的异步代码,而不必担心不同平台的底层实现差异。

在 NuttX 系统中集成 libuv,可以为实时操作系统带来强大的网络和 I/O 能力,促进更多应用程序在嵌入式设备上的开发。

相关文章:

  • 介质访问控制——随机访问控制
  • 大模型笔记5:Agent
  • 企业信息技术外包管理制度:如何安全高效管理IT外包服务
  • NodeJS的yarn和npm作用和区别,为什么建议用yarn
  • 分类预测 | Matlab基于AOA-VMD-GRU故障诊断分类预测
  • 3.创建数据库
  • 深度学习---ONNX(Open Neural Network Exchange)
  • 路由的相关知识
  • Python•元组集合字符串
  • 山东大学项目实训-创新实训-法律文书专家系统-项目报告(七)
  • C# 枚举(位标志)
  • GO语言---短变量声明
  • C#最佳实践:为何应减少嵌套
  • Adguard安卓版:全方位广告拦截与隐私保护
  • vue3 +spring boot文件上传
  • Compose Canvas 中添加手势控制
  • ​​信息系统项目管理师-项目范围管理 知识点总结与例题分析​​
  • Sa-Token全面深入学习指南
  • 敏捷开发的特点
  • 【 C++ 模板中 `template<typename T>` 与 `template<class T>` 的深度解析】
  • 营销网站开发找哪家/整合营销策略有哪些
  • 简述网站推广方式/南宁百度seo排名价格
  • 定制 网站开发 价格/app推广怎么做
  • 兰山网站建设/长尾关键词挖掘网站
  • 广州 骏域网站建设 陶瓷/墨子学院seo
  • 做网站前端设计需要哪些证书/新媒体口碑营销案例