本文介绍了netlink和libnl。
Netlink is used to transfer information between kernel and user-space processes. It consists of a standard sockets-based interface for user space processes and an internal kernel API for kernel modules.
Netlink是基于socket的用户空间进程和内核态进程通信的方式。 用途有两个,
这里不得不插一句,socket真是个牛逼的工具:
创建一个Netlink socket的方式如下
netlink_socket = socket(AF_NETLINK, socket_type, netlink_family);
实际上domain和socket_type都是固定的,其中socket_type可以是SOCK_DGRAM,但是不予区分。所以创建一个netlink socket的接口基本如下
netlink_socket = socket(AF_NETLINK, SOCK_RAW, netlink_family);
变化的只是netlink_family,socket的第三个参数protocol,为了说明netlink_family的作用,先看看通常的UDP/TCP socket的创建方式
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
通过here 发现UDP是SOCK_DGRAM类型的默认协议,TCP是SOCK_STREAM类型的默认协议,所以也可以写成
udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
那么netlink_family的作用是什么?
netlink_family selects the kernel module or netlink group to communicate with. --netlink manual
The protocol specifies a particular protocol to be used with the socket. Normally only a single protocol exists to support a particular socket type within a given protocol family, in which case protocol can be specified as 0. However, it is possible that many protocols may exist, in which case a particular protocol must be specified in this manner. The protocol number to use is specific to the “communication domain” in which communication is to take place; -- socket manual
socket手册对protocol的解释是,如果socket_type不能唯一标识通信协议,就要用protocol来指定明确的通信“协议”(封装标准)。
所以这个protocol就是指定通信标准,常用的网络编程主要是TCP/UDP socket,该参数设置为0,用默认的协议,导致了在netlink socket上的疑虑。 netlink_family 列表见man7.org
这里有一个Netlink实例
在内核中PF_NETLINK和AF_NETLINK是一个东西,证据在此
unix domain socket 用 pid来标识两个进程。 -netlink socket 用pid来标识两个进程 ?
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. */
};
nl_pid is the unicast address of netlink socket. It's always 0 if the destination is in the kernel. For a user-space process, nl_pid is usually the PID of the process owning the destination socket. However, nl_pid identifies a netlink socket, not a process.
nl_pid在用户空间能标识一个进程,在内核空间通过netlink_kernel_create
创建socket并注册消息处理函数(每次收到数据后调用)。
用户态进程发送的数据怎么交付给内核态进程? 应该是nl_family
?细节尚未搞懂。
The libnl suite is a collection of libraries providing APIs to netlink protocol based Linux kernel interfaces.
libnl 库封装了netlink socket 底层操作,提供了一系列高级API,简化了netlink编程。 libnl 包含四个主要的lib
如下图所示
从图中可以清楚的看出,原来需要直接操作socket接口的工作,现在可以用libnl来间接完成。
stackoverflow上同样有一个类似【实例1】的程序,区别在于其用libnl实现,libnl example
根据内核提供的taskstats接口,分析用libnl实现的taskstats监控程序,理解netlink在内核的工作原理。