#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
netlink_socket = socket(AF_NETLINK, socket_type, netlink_family);
1 netlink socket
NetLink被用于在内核和应用之前传输信息,在用户空间编程使用标准的socket相关的API接口,在内核空间使用kernel内部的API接口。
NetLink是一个面向数据报的服务,socket_type 可以是SOCK_RAW也可以是SOCK_DGRAM ,在netlink协议中不做区分。
netlink_family最常用的就是NETLINK_ROUTE用于网络相关的配置和NETLINK_KOBJECT_UEVENT用于设备热插拔监测。
2 socket 地址
struct sockaddr_nl {
sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* Zero */
pid_t nl_pid; /* Port ID */
__u32 nl_groups; /* Multicast groups mask */
};
使用socket通信肯定需要自身的地址和对方的地址。netlink socket使用struct sockaddr_nl作为通信的地址。
2.1 nl_pid
nl_pid是netlink socket的单播地址,类似于网络通信中的端口号,网络地址通常是ip+port,但是netlink是本地通信,所以有port就够了。
在netlink中,如果目的地址是内核,也就是说接收方是内核,那么目的地址的nl_pid就是0.
在用户空间,如果目的地址是应用程序,也就是说接收方是应用程序,那么目的地址的nl_pid通常是进程自己的PID号。但是比如在进程中创建多个netlink socktet,但是进程号是唯一的,多个socket不能使用相同的nl_pid,那么该怎么办,两个办法,在bind()调用之前,手动分配一个唯一的nl_pid或者将nl_pid设置为0,这样bind()的时候由内核自动分配一个唯一的nl_pid,和网络通信中的端口号非常像,就是手动指定和默认分配。
2.2 nl_groups
这个域类似于组播,就是内核会发送数据给一组net socketet,如果用户空间程序的netlink socket,在bind()的地址中的nl_groups指定了接收组,那就可以接收内核发送的数据,通俗的讲就是内核对多个应用通信,这个有什么用呢,非常有用,比如有硬件设备热插拔,内核可以发布这个消息到组,然后每一个bind()了这个组的应用程序,都可以接收热插拔消息。nl_groups更多时候就是用于用户程序监测内核事件,比如热插拔事件,网络管理事件等。每个socket 地址中接收32种组消息,因为nl_groups是32位数,每一位代表一个不同的组类型。
比如想接收(监听)网卡事件和I地址变化,可以设置nl_groups =RTMGRP_LINK | RTMGRP_IPV4_IFADDR 。
参考链接
netlink(7) - Linux manual pagehttps://man7.org/linux/man-pages/man7/netlink.7.html