Linux基础 -- 用户态Generic Netlink库高性能接收与回调框架

[复制链接]
发表于 2025-5-17 21:44:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
用户态Generic Netlink库高性能接收与回调框架

一、概述

在 Linux 系统中,Netlink 是用户态与内核态通信的强盛机制。libnl 是一个专为简化 Netlink 编程而设计的库,提供了接收和处置惩罚 Netlink 消息的高级接口。libnl-genl 是其通用 Netlink (Generic Netlink) 扩展库,专门用于处置惩罚自界说协议。本文将具体介绍怎样通过 nl_socket_modify_cb 和 nl_cb_set 两种方法实现高效的 Netlink 消息接收和处置惩罚框架。
二、Netlink 回调机制

Netlink 使用回调机制来处置惩罚接收到的消息。常用的回调设置方法有两种:
1. nl_socket_modify_cb



  • 仅在指定的 Netlink 套接字上设置回调。
  • 适合在每个套接字上使用不同回调。
2. nl_cb_set



  • 在回调上下文 (struct nl_cb *) 上设置回调。
  • 可以在多个套接字之间共享。
三、高效 Netlink 接收框架(libnl + libnl-genl + epoll)

1. epoll + 非壅闭 + 批量接收



  • 使用 epoll 举行非壅闭监听。
  • 通过大缓冲区批量接收消息。
  • 联合 libnl 和 libnl-genl 实现高效的 Netlink 消息接收。
2. 完备示例:Generic Netlink 消息接收 + epoll

  1. #include <netlink/netlink.h>
  2. #include <netlink/msg.h>
  3. #include <netlink/genl/genl.h>
  4. #include <netlink/genl/ctrl.h>
  5. #include <sys/epoll.h>
  6. #include <stdio.h>
  7. #include <fcntl.h>
  8. #include <unistd.h>
  9. #define MY_GENL_FAMILY "my_custom_family"
  10. // 自定义消息处理回调
  11. int my_genl_handler(struct nl_msg *msg, void *arg) {
  12.         struct nlmsghdr *nlh = nlmsg_hdr(msg);
  13.         struct genlmsghdr *gnlh = nlmsg_data(nlh);
  14.    
  15.         printf("[Genl Handler] Received a Netlink message.\n");
  16.         printf("Command: %d, Version: %d\n", gnlh->cmd, gnlh->version);
  17.        
  18.         struct nlattr *attrs[GENL_MAX_ATTRS + 1] = {};
  19.         nla_parse(attrs, GENL_MAX_ATTRS, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
  20.        
  21.         if (attrs[GENL_ATTR_MSG]) {
  22.                 printf("Message: %s\n", nla_get_string(attrs[GENL_ATTR_MSG]));
  23.         }
  24.        
  25.     return NL_OK;
  26. }
  27. // 设置非阻塞模式
  28. void set_nonblocking(int fd) {
  29.     int flags = fcntl(fd, F_GETFL, 0);
  30.     fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  31. }
  32. int main() {
  33.     struct nl_sock *sock = nl_socket_alloc();
  34.     nl_connect(sock, NETLINK_GENERIC);
  35.     // 查找 Generic Netlink family
  36.     int family_id = genl_ctrl_resolve(sock, MY_GENL_FAMILY);
  37.     if (family_id < 0) {
  38.         printf("[Error] Could not resolve Generic Netlink family\n");
  39.         return -1;
  40.     }
  41.     struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
  42.     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_genl_handler, NULL);
  43.     nl_socket_set_cb(sock, cb);
  44.     int fd = nl_socket_get_fd(sock);
  45.     set_nonblocking(fd);
  46.     int epfd = epoll_create1(0);
  47.     struct epoll_event ev, events[10];
  48.     ev.events = EPOLLIN;
  49.     ev.data.fd = fd;
  50.     epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
  51.     while (1) {
  52.         int nfds = epoll_wait(epfd, events, 10, -1);
  53.         for (int i = 0; i < nfds; i++) {
  54.             if (events[i].data.fd == fd) {
  55.                 nl_recvmsgs(sock, cb); // 使用 libnl + epoll 处理消息
  56.             }
  57.         }
  58.     }
  59.     nl_cb_put(cb);
  60.     nl_close(sock);
  61.     nl_socket_free(sock);
  62.     close(epfd);
  63.     return 0;
  64. }
复制代码
3. 多线程处置惩罚(可选)



  • 通过线程池并行处置惩罚接收到的 Netlink 消息。
  • 每个线程从 epoll 事件队列中读取并剖析 Netlink 消息。
四、最佳实践



  • 通过 nl_socket_modify_cb 灵活调解特定套接字的回调。
  • 通过 nl_cb_set 设置全局回调,并在多套接字间复用。
  • 对于高频 Netlink 通信,采用非壅闭模式 + epoll + 批量处置惩罚。
  • 使用 libnl-genl 处置惩罚 Generic Netlink,简化自界说协议实现。
五、总结

本框架提供了一种高效的 Netlink 消息接收和处置惩罚方式,实用于高并发和高性能场景,并支持自界说协议的灵活扩展。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表