当前位置: 首页 > 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值是唯一的。

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

http://www.xdnf.cn/news/15751.html

相关文章:

  • 基于微信小程序的中医小妙招系统的设计与实现
  • 使用dompurify修复XSS跨站脚本缺陷
  • k8s 调整Node节点 Max_Pods
  • dify本地部署,docker-plugin_daemon-1启动不了,一直报错
  • rtps报文分析
  • 2025年消防设施操作员考试题库及答案
  • Windows 11设置开机自动运行 .jar 文件
  • 实战篇|多总线网关搭建与量产验证(5000 字深度指南)
  • 第五章、SpringBoot与消息通信(一)
  • useMemo + memo + useContext 性能优化实战:从无感重渲染到丝滑体验
  • 深入理解 Android Handler
  • Rocky8 升级 Python 3.9.20 并部署 Airflow 2.10.5
  • STM32F407的引脚说明
  • ActivityRecord、TaskRecord、ActivityStack、ActivityStackSupervisor、ProcessRecord
  • 【工具】在Cursor/VS Code中配置Python调试环境的完整指南
  • VASP 6.4.1 Ubuntu系统编译安装手册
  • STM32学习2
  • LeadeRobot具身智能应用标杆:无人机X柔韧具身智能,空中精准作业游刃有余
  • Python 浮点数运算之谜:深入解析round(0.675, 2)等输出异常
  • 人工智能在WEB开发中的应用与实践
  • string函数具体事例
  • 数字化音乐教育软件 UI 设计的关键要点
  • 如何删除 Launchpad 中 Chrome 的图标
  • orcad csi 17.4 DRC规则设置及检查
  • 使用人工智能大模型kimi,如何免费制作PPT?
  • flutter app实现分辨率自适应的图片资源加载
  • 论文阅读:2023 arxiv Safe RLHF: Safe Reinforcement Learning from Human Feedback
  • Git-使用教程(新手向)
  • STM32CubeMX-H7-15-SPI通信协议读写W25Q64
  • 【springsecurity oauth2授权中心】简单案例跑通流程