一定要让你明白什么是 Netlink

本文深入探讨了内核和用户空间Netlink套接字的创建过程,详细解析了从__netlink_create到SyS_socket的调用流程,以及netlink_ops结构中关键函数的作用。

内核netlink 套接字 和 用户空间netlink套接字都会调用下面的这个函数 来创建一个sock
在这里插入图片描述

/*
	调用流程:
	 0xffffff80089c7790 : __netlink_create+0x0/0xe4 [kernel]
	 0xffffff80089c7d70 : netlink_create+0x1ec/0x26c [kernel]
	 0xffffff8008989d50 : __sock_create+0x11c/0x180 [kernel]
	 0xffffff8008989e00 : sock_create+0x4c/0x5c [kernel]
	 0xffffff800898ad6c : SyS_socket+0x48/0xd0 [kernel]
	 0xffffff8008082f30 : el0_svc_naked+0x24/0x28 [kernel]
	 0x0 (inexact)
*/
static int __netlink_create(struct net *net, 
									struct socket *sock,
			    					struct mutex *cb_mutex, 
			    					int protocol,
			    					int kern)
{
	....
	/*
		用户空间调用 bind() connect() .....
		会在这里进行响应:
		
		static const struct proto_ops netlink_ops = {
		.family =	PF_NETLINK,
		.owner =	THIS_MODULE,
		.release =	netlink_release,
		.bind =		netlink_bind,
		...
		.shutdown =	sock_no_shutdown,
		.setsockopt =	netlink_setsockopt,
	};
	*/
	sock->ops = &netlink_ops;
}
NETLINK 通信是一种 Linux 内核与用户空间进程之间进行双向通信的机制。它是一种基于 socket 的 IPC(进程间通信)方式,允许内核向用户空间发送消息,也允许用户空间程序向内核发送消息。NETLINK 通信广泛用于网络配置、路由管理、设备监控等场景。 ### NETLINK 通信的特点: 1. **双向通信**:用户空间和内核空间可以互相发送消息。 2. **异步通信**:通信过程是异步的,适用于事件驱动的场景。 3. **支持多种协议类型**:不同的 NETLINK 协议类型用于不同的内核子系统,如 NETLINK_ROUTE(路由信息)、NETLINK_KOBJECT_UEVENT(设备事件)等。 4. **多播支持**:多个用户空间进程可以同时监听来自内核的消息。 ### 使用 NETLINK 通信的基本步骤: 1. **创建 socket**:使用 `socket(PF_NETLINK, SOCK_RAW, protocol)` 创建一个 NETLINK socket。 2. **绑定地址**:通过 `bind()` 函数绑定 socket 到一个或多个多播组。 3. **发送消息**:用户空间进程可以通过 `sendto()` 或 `sendmsg()` 向内核发送消息。 4. **接收消息**:通过 `recvfrom()` 或 `recvmsg()` 接收来自内核的消息。 ### 示例代码(用户空间接收内核消息): ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <linux/netlink.h> #define NETLINK_USER 31 // 自定义协议号 struct sockaddr_nl src_addr, dest_addr; struct nlmsghdr *nlh = NULL; struct iovec iov; int sock_fd; struct msghdr msg; int main() { // 创建 NETLINK socket sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER); if (sock_fd < 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } // 绑定地址 memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); // 使用当前进程 PID 作为唯一标识 src_addr.nl_groups = 0; // 不加入多播组 bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)); // 准备接收消息 nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(1024)); iov.iov_base = (void *)nlh; iov.iov_len = NLMSG_SPACE(1024); memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iov; msg.msg_iovlen = 1; printf("Waiting for message from kernel...\n"); while (1) { recvmsg(sock_fd, &msg, 0); printf("Received message: %s\n", NLMSG_DATA(nlh)); } close(sock_fd); free(nlh); return 0; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值