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

Netlink套接字

netlink套接字

        Netlink套接字是专门用于用户控件与内核之间的通讯,尤其是监听uevent事件(热插拔,模块加载等);

socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);

AF_NETLINK:Netlink协议族

SOCK_DGRAM:数据报模式(尽管 Netlink 是可靠的);

SOCK_CLOEXEC:设置 close-on-exec 标志,防止套接字被 exec() 继承。

NETLINK_KOBJECT_UEVENT:指定 Netlink 子协议,用于接收内核发出的 uevent 事件(如设备插拔)。

sockaddr_nl结构体

#include <linux/netlink.h>struct sockaddr_nl {sa_family_t     nl_family;  // 地址族,固定为 AF_NETLINKunsigned short  nl_pad;     // 填充字段,通常为 0pid_t           nl_pid;     // 进程的唯一标识(通常是进程 PID 或 0)__u32           nl_groups;  // 多播组掩码(订阅的组别)
};

nl_family:地址族,必须设为 AF_NETLINK,表示 Netlink 通信。

nl_pad:保留字段,初始化为0

nl_pid:端口ID

        用户空间:通常设为进程 PID(用于单播通信)。

        内核:固定为 0。

nl_groups:多播组源码

        0:仅接收单播消息

        非零:订阅指定的多播组

uevent

        Linux 系统中的一种事件通知机制,用于向用户空间发送有关内核和设备状态变化的通知。通常用于设备驱动程序、热插拔事件以及设备状态变化等场景,以便用户空间应用程序能够在这些事件发生时做出相应的响应。

代码示例

int fd = socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
if (fd < 0) {perror("socket");exit(1);
}
struct sockaddr_nl addr = {.nl_family = AF_NETLINK,.nl_pid = getpid(),    // 当前进程 PID 作为地址.nl_groups = 1,        // 订阅内核广播组
};
bind(fd, (struct sockaddr*)&addr, sizeof(addr));
char buf[4096];
while (1) {ssize_t len = recv(fd, buf, sizeof(buf), 0);if (len > 0) {parse_uevent(buf, len); // 解析 uevent 消息}
}

uevent消息

        uevent消息是 key=value 形式的字符串序列,以 \0 分隔,末尾双 \0。以mmc为例:

#方便观看
remove@/devices/soc0/soc/1f282600.sstar_sdmmc0/mmc_host/mmc0/mmc0:b369\0
ACTION=remove\0
DEVPATH=/devices/soc0/soc/1f282600.sstar_sdmmc0/mmc_host/mmc0/mmc0:b369\0
SUBSYSTEM=mmc\0
MMC_TYPE=SD\0
MMC_NAME=SDABC\0
MODALIAS=mmc:block\0
SEQNUM=446\0\0
#实际字符串
remove@/devices/soc0/soc/1f282600.sstar_sdmmc0/mmc_host/mmc0/mmc0:b369\0ACTION=remove\0DEVPATH=/devices/soc0/soc/1f282600.sstar_sdmmc0/mmc_host/mmc0/mmc0:b369\0SUBSYSTEM=mmc\0MMC_TYPE=SD\0MMC_NAME=SDABC\0MODALIAS=mmc:block\0SEQNUM=446\0\0

几个关键的key

ACTION:事件类型

DEVPATH:设备在内核中的路径(对应 /sys 下的路径)

SUBSYSTEM:子系统

DEVNAME:设备节点名

MAJOR:主设备号

MINOR:次设备号

SEQNUM:事件序列号(用于去重)

ACTION

用于描述设备或模块的状态变化,核心值如下:

add:新设备或者模块被添加到内核中;例如:插入sd卡,插入usb设备,加载驱动等

remove:设备或者模块从内核中移除;例如:拔出sd卡,拔出usb设备,卸载驱动等

change:设备或者模块的状态发生变化;例如:sd卡格式化

move:设备路径变更;例如:设备重命名,重新挂载其他路径

bind:设备与驱动绑定成功;例如:插入sd卡,并且sd卡被识别

unbind:设备与驱动解绑;例如:拔出sd卡

online:设备变为可用状态;

offline:设备变为不可用状态;

SUBSYSTEM

表示事件所属的内核子系统,用于分类设备或模块的类型。

block:块设备;例如:磁盘分区等

mmc:MMC/SD 卡设备

usb:usb设备;例如:主机控制器、存储设备、HID设备等

net:网络设备;例如:网卡、虚拟接口

pci:pci设备;例如:显卡,网卡

sound:音频设备;例如:麦克,声卡

tty:串行终端设备;例如串口

power_supply:电源设备;例如:电池,适配器

        注意:不同的子系统也会有自己独有的key;例如:SUBSYSTEM=mmc; 会有MMC_TYPE;MMC_NAME等专属属性

SEQNUM

        用于标识事件的唯一性和顺序。是一个单调递增的数值,从1 开始递增,直到溢出后循环;由内核在生成 uevent 时分配。因此每个事件的SEQNUM值是唯一的。

        有时候内核可能某个事件发送多次;可以判断这个值,丢弃重复的即可;所以该值具有去重的功能。

相关文章:

  • Starrocks 数据均衡DiskAndTabletLoadReBalancer的实现
  • DBeaver连接hive
  • DasViewer是什么?如何安装?
  • AI 组件库是什么?如何影响UI的开发?
  • 华为OD机试真题——最长的顺子(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
  • PyTorch 浮点数精度全景:从 float16/bfloat16 到 float64 及混合精度实战
  • PyTorch分布式训练调试方法(跟踪调用过程)
  • java 排序算法-快速排序
  • # 使用 PyTorch 构建并训练一个简单的 CNN 模型进行图像分类
  • Oracle日志系统之附加日志
  • uni-app 安卓10以上上传原图解决方案
  • 2025妈妈杯数学建模D题完整分析论文(共42页)(含模型建立、代码)
  • uniapp运行在app端如何使用缓存
  • GPU 在机器学习中的应用优势:从技术特性到云端赋能
  • 神经网络优化 - 小批量梯度下降之批量大小的选择
  • CCF CSP 第36次(2024.12)(2_梦境巡查_C++)
  • 初创企业机器学习训练:云服务器配置对效率、成本与可扩展性的影响
  • Python项目--基于机器学习的股票预测分析系统
  • 鸿蒙语言基础
  • c#开发大冲锋游戏登录器
  • 经济日报金观平:统筹国内经济工作和国际经贸斗争
  • 巴黎奥运后红土首秀落败,郑钦文止步马德里站次轮
  • 云南鲁甸县一河滩突然涨水致4死,有人在救人过程中遇难
  • 印媒称印巴在克什米尔控制线沿线发生小规模交火,巴方暂未回应
  • 印度加大应对力度,吊销所有巴基斯坦公民签证
  • 厚植民营企业家成长土壤是民营经济高质量发展的关键