扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

Hook 机制在嵌入式中的应用解析!

1小时前
113
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

大家好,我是杂烩君。今天给大家带来一篇干货满满的技术文章——深入解析evhtp HTTP服务器中的Hook机制

嵌入式中,我们经常需要在不修改核心代码的前提下扩展功能,而Hook机制恰好就是解决这个问题的利器。

1. Hook机制是什么?

Hook,中文翻译为"钩子",形象地描述了它的作用——在程序执行流程的关键节点"挂上"自定义的处理函数

打个通俗的比方:假如你在工厂流水线上工作,每个产品经过你的工位时,你可以检查质量、添加零件或者记录日志。Hook机制就像是在软件的"流水线"上预留的工位,让你可以插入自己的处理逻辑。

使用Hook机制带来的好处:

低耦合:核心业务代码和扩展功能分离

可扩展:新增功能无需修改原有代码

可复用:Hook函数可在多个场景复用

易维护:功能模块化,定位问题更快

性能可控:按需启用Hook,零成本关闭

2. evhtp的Hook示例

关于evhtp的介绍可看往期文章:一款专为嵌入式系统设计的开源HTTP库——libevhtp

下面给出一个完整的可运行示例,演示如何使用evhtp的Hook机制:

#include <evhtp.h>
#include <sys/queue.h>
#include <string.h>
#include <stdio.h>
#include <time.h>

// Hook函数:记录请求开始
evhtp_res on_headers_start(evhtp_request_t *req, void *arg) 
{
    printf("[%ld] 开始解析请求头n", time(NULL));
    fflush(stdout);
    return EVHTP_RES_OK;
}

// Hook函数:检查每个header
evhtp_res on_header(evhtp_request_t *req, evhtp_header_t *hdr, void *arg) 
{
    printf("  Header: %s = %sn", hdr->key, hdr->val);
    fflush(stdout);
    return EVHTP_RES_OK;
}

// Hook函数:请求头解析完成
evhtp_res on_headers(evhtp_request_t *req, evhtp_headers_t *hdrs, void *arg) 
{
    // 手动统计header数量
    int count = 0;
    evhtp_header_t *header;
    TAILQ_FOREACH(header, hdrs, next) {
        count++;
    }
    
    printf("[%ld] 请求头解析完成,共 %d 个n", time(NULL), count);
    fflush(stdout);
    return EVHTP_RES_OK;
}

// Hook函数:接收body数据
evhtp_res on_body(evhtp_request_t *req, evbuf_t *buf, void *arg) 
{
    size_t len = evbuffer_get_length(buf);
    printf("  收到Body数据: %zu 字节n", len);
    fflush(stdout);
    return EVHTP_RES_OK;
}

// 业务回调函数
void request_handler(evhtp_request_t *req, void *arg) 
{
    printf("[业务处理] %sn", req->uri->path->full);
    fflush(stdout);
    
    evbuffer_add_printf(req->buffer_out, "Hello from evhtp!n");
    evhtp_send_reply(req, EVHTP_RES_OK);
}

int main(int argc, char **argv) 
{
    struct event_base *evbase = event_base_new();
    evhtp_t *htp = evhtp_new(evbase, NULL);
    
    printf("================= Embedded HTTP Server Demo =================n");
    
    // 设置业务回调
    evhtp_set_cb(htp, "/api/test", request_handler, NULL);
    
    // 获取回调并设置Hook
    evhtp_callback_t *cb = evhtp_get_cb(htp, "/api/test");
    
    evhtp_callback_set_hook(cb, evhtp_hook_on_headers_start, 
                           (evhtp_hook)on_headers_start, NULL);
    evhtp_callback_set_hook(cb, evhtp_hook_on_header, 
                           (evhtp_hook)on_header, NULL);
    evhtp_callback_set_hook(cb, evhtp_hook_on_headers, 
                           (evhtp_hook)on_headers, NULL);
    evhtp_callback_set_hook(cb, evhtp_hook_on_read, 
                           (evhtp_hook)on_body, NULL);
    
    evhtp_bind_socket(htp, "0.0.0.0", 8080, 1024);
    
    printf("server start at: http://0.0.0.0:8080n");
    
    event_base_loop(evbase, 0);
    
    evhtp_free(htp);
    event_base_free(evbase);
    return0;
}

编译运行

gcc -o hook_demo hook_demo.c -levhtp -levent
./hook_demo

测试指令:

curl -X POST http://localhost:8080/api/test -d 'hello'

测试输出

3. evhtp的Hook实现原理

接下来我们深入源码,看看evhtp是如何实现Hook机制的。

3.1 Hook数据结构

evhtp的Hook存储结构如下:

evhtp提供了丰富的Hook点覆盖整个请求处理流程:

Hook类型 触发时机 常用场景
on_headers_start 开始解析请求头 请求预处理、计时开始
on_header 解析每个请求头 Header校验、日志记录
on_headers 所有请求头解析完成 认证鉴权、请求路由
on_path URL路径解析完成 路径重写、权限检查
on_read 接收到Body数据 数据校验、流式处理
on_request_fini 请求处理完成 资源清理、统计上报
on_connection_fini 连接关闭 连接池管理、清理
on_connection_error 连接错误 连接错误处理
on_error 发生错误 错误处理、告警
on_new_chunk 新chunk开始 Chunked编码处理
on_chunk_fini Chunk完成 Chunk数据处理
on_chunks_fini 所有Chunks完成 完整Body处理
on_hostname 主机名解析完成 虚拟主机路由
on_write 写入数据 响应拦截、日志
on_event 事件触发 事件处理

3.2 Hook调用机制

evhtp定义了两个宏来统一Hook调用逻辑。一个支持可变参数,一个不支持额外参数。

这两个宏调最终调用的就是上层设置的Hook函数。这两个宏实现了两层Hook查找

    先查找request级别的Hook如果没有,再查找connection级别的Hook

3.3 Hook设置函数

evhtp提供了统一的Hook设置接口:

3.4 Hook实际调用点

以header解析为例:

对应的Hook调用函数:

3.5 完整的Hook调用流程

在HTTP请求处理过程中,Hook的调用顺序如下:

4. 总结

Hook机制是软件设计中的重要模式,尤其适合嵌入式系统中需要灵活扩展的场景。通过evhtp的实现,我们学到了:Hook机制通过函数指针实现在关键节点插入自定义逻辑、丰富的Hook点覆盖了HTTP请求处理的全生命周期。

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

本公众号专注于嵌入式技术,包括但不限于C/C++、嵌入式、物联网、Linux等编程学习笔记,同时,公众号内包含大量的学习资源。欢迎关注,一同交流学习,共同进步!