如何玩转linux内核netlink通信机制,从这三点入手!
一、什么是Netlink通信机制
Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。
Netlink 是一种特殊的 socket,它是 Linux 所特有的,类似于 BSD 中的AF_ROUTE 但又远比它的功能强大,目前在Linux 内核中使用netlink 进行应用与内核通信的应用很多; 包括:路由 daemon(NETLINK_ROUTE),用户态 socket 协议(NETLINK_USERSOCK),防火墙(NETLINK_FIREWALL),netfilter 子系统(NETLINK_NETFILTER),内核事件向用户态通知(NETLINK_KOBJECT_UEVENT),通用 netlink(NETLINK_GENERIC)等。
Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 netlink。
Netlink 相对于系统调用,ioctl 以及 /proc文件系统而言具有以下优点:
netlink使用简单,只需要在include/linux/netlink.h中增加一个新类型的 netlink 协议定义即可,(如 #define NETLINK_TEST 20 然后,内核和用户态应用就可以立即通过 socket API 使用该 netlink 协议类型进行数据交换);
netlink是一种异步通信机制,在内核与用户态应用之间传递的消息保存在socket缓存队列中,发送消息只是把消息保存在接收者的socket的接收队列,而不需要等待接收者收到消息;
使用 netlink 的内核部分可以采用模块的方式实现,使用 netlink 的应用部分和内核部分没有编译时依赖; netlink 支持多播,内核模块或应用可以把消息多播给一个netlink组,属于该neilink 组的任何内核模块或应用都能接收到该消息,内核事件向用户态的通知机制就使用了这一特性;
内核可以使用 netlink 首先发起会话;
二、Netlink常用数据结构及函数
用户态应用使用标准的 socket API有(sendto()),recvfrom(); sendmsg(), recvmsg())
下面简单介绍几种NETLINK用户态通信的常用数据结构
【文章福利】小编推荐自己的Linux内核技术交流群:【891587639】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前100名进群领取,额外赠送一份价值699的内核资料包(含视频教程、电子书、实战项目及代码)


1、用户态数据结构
Netlink通信跟常用UDP Socket通信类似:
struct sockaddr_nl 是netlink通信地址跟普通socket struct sockaddr_in类似
struct sockaddr_nl结构:
struct nlmsghd结构:
nlmsg_len:整个netlink消息的长度(包含消息头);
nlmsg_type:消息状态,内核在include/uapi/linux/netlink.h中定义了以下4种通用的消息类型,它们分别是:
3. nlmsg_flags:消息标记,它们用以表示消息的类型,如下
4. nlmsg_seq:消息序列号,用以将消息排队,有些类似TCP协议中的序号(不完全一样),但是netlink的这个字段是可选的,不强制使用;
5. nlmsg_pid:发送端口的ID号,对于内核来说该值就是0,对于用户进程来说就是其socket所绑定的ID号。
struct msghdr 结构体
2、netlink 内核数据结构、常用宏及函数:
netlink消息类型:
netlink常用宏:
netlink 内核常用函数:
netlink_kernel_create内核函数用于创建 内核socket用用户态通信
单播netlink_unicast()和 多播netlink_broadcast()
三、netlink实例
(1)用户态程序 (sendto(), recvfrom())
Netlink 内核模块代码:
Makeflie:
运行结果:
首先将编译出来的Netlink内核模块插入到系统当中(insmod netlink_test.ko)可以看到如下:
接着运行应用程序:./a.out
