马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
Netlink多播组消息处理技术文档
概述
Netlink是一种用户态与内核态之间通信的机制,支持单播和多播模式。多播组答应多个用户态进程接收同一组的广播消息,广泛应用于网络变乱、系统通知等场景。
本文将详细先容如安在内核态发送多播组消息,以及用户态如何接收并处理这些消息。
内核态:发送多播组消息
实现步调
- 创建Netlink套接字:通过netlink_kernel_create创建一个Netlink套接字。
- 构建消息:填充nlmsghdr头部和数据部分。
- 发送消息:利用netlink_broadcast将消息广播到指定多播组。
示例代码
- #include <linux/module.h>
- #include <linux/netlink.h>
- #include <net/sock.h>
- #include <linux/skbuff.h>
- #define NETLINK_USER 31
- #define MULTICAST_GROUP1 (1 << 0)
- #define MULTICAST_GROUP2 (1 << 1)
- static struct sock *nl_sock = NULL;
- // 初始化Netlink套接字
- static int __init netlink_init(void) {
- struct netlink_kernel_cfg cfg = {
- .groups = MULTICAST_GROUP1 | MULTICAST_GROUP2, // 支持的多播组
- .input = NULL, // 无需接收消息
- };
- nl_sock = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
- if (!nl_sock) {
- printk(KERN_ERR "Failed to create Netlink socket\n");
- return -ENOMEM;
- }
- printk(KERN_INFO "Netlink socket created\n");
- return 0;
- }
- // 向多播组发送消息
- static void send_multicast_message(const char *message, uint32_t group) {
- struct sk_buff *skb;
- struct nlmsghdr *nlh;
- int msg_size = strlen(message) + 1;
- skb = nlmsg_new(msg_size, GFP_KERNEL);
- if (!skb) {
- printk(KERN_ERR "Failed to allocate sk_buff\n");
- return;
- }
- nlh = nlmsg_put(skb, 0, 0, NLMSG_DONE, msg_size, 0);
- strcpy(nlmsg_data(nlh), message);
- netlink_broadcast(nl_sock, skb, 0, group, GFP_KERNEL);
- printk(KERN_INFO "Message sent to group %u: %s\n", group, message);
- }
- // 模块加载函数
- static int __init netlink_multicast_init(void) {
- int ret = netlink_init();
- if (ret) return ret;
- send_multicast_message("Hello Group 1", MULTICAST_GROUP1);
- send_multicast_message("Hello Group 2", MULTICAST_GROUP2);
- return 0;
- }
- // 模块卸载函数
- static void __exit netlink_multicast_exit(void) {
- if (nl_sock) {
- netlink_kernel_release(nl_sock);
- printk(KERN_INFO "Netlink socket released\n");
- }
- }
- module_init(netlink_multicast_init);
- module_exit(netlink_multicast_exit);
- MODULE_LICENSE("GPL");
复制代码 用户态:接收多播组消息
实现步调
- 创建Netlink套接字:利用socket()创建用户态的Netlink套接字。
- 订阅多播组:通过setsockopt()将套接字加入一个或多个多播组。
- 接收消息:利用recvmsg()从套接字中接收消息。
- 处理消息:解析nlmsghdr头部并处理数据。
示例代码
- #include <linux/netlink.h>
- #include <sys/socket.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <unistd.h>
- #define NETLINK_USER 31
- #define MULTICAST_GROUP1 (1 << 0)
- #define MULTICAST_GROUP2 (1 << 1)
- #define MAX_PAYLOAD 1024
- struct nl_msg {
- struct nlmsghdr hdr;
- char data[MAX_PAYLOAD];
- };
- // 初始化Netlink套接字并订阅多播组
- int init_netlink_socket(int *sock_fd, uint32_t groups) {
- struct sockaddr_nl src_addr;
- *sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
- if (*sock_fd < 0) {
- perror("socket");
- return -1;
- }
- memset(&src_addr, 0, sizeof(src_addr));
- src_addr.nl_family = AF_NETLINK;
- src_addr.nl_pid = getpid(); // 当前进程PID
- src_addr.nl_groups = groups;
- if (bind(*sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0) {
- perror("bind");
- close(*sock_fd);
- return -1;
- }
- if (setsockopt(*sock_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &groups, sizeof(groups)) < 0) {
- perror("setsockopt NETLINK_ADD_MEMBERSHIP");
- close(*sock_fd);
- return -1;
- }
- return 0;
- }
- // 动态加入多播组
- int join_multicast_group(int sock_fd, uint32_t group) {
- if (setsockopt(sock_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)) < 0) {
- perror("setsockopt NETLINK_ADD_MEMBERSHIP");
- return -1;
- }
- printf("Joined multicast group: %u\n", group);
- return 0;
- }
- // 动态退出多播组
- int leave_multicast_group(int sock_fd, uint32_t group) {
- if (setsockopt(sock_fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group)) < 0) {
- perror("setsockopt NETLINK_DROP_MEMBERSHIP");
- return -1;
- }
- printf("Left multicast group: %u\n", group);
- return 0;
- }
- // 接收并处理消息
- void receive_messages(int sock_fd) {
- struct nl_msg msg;
- struct sockaddr_nl src_addr;
- struct iovec iov;
- struct msghdr msghdr;
- while (1) {
- memset(&msg, 0, sizeof(msg));
- memset(&src_addr, 0, sizeof(src_addr));
- memset(&msghdr, 0, sizeof(msghdr));
- iov.iov_base = &msg;
- iov.iov_len = sizeof(msg);
- msghdr.msg_name = &src_addr;
- msghdr.msg_namelen = sizeof(src_addr);
- msghdr.msg_iov = &iov;
- msghdr.msg_iovlen = 1;
- int ret = recvmsg(sock_fd, &msghdr, 0);
- if (ret < 0) {
- perror("recvmsg");
- break;
- }
- printf("Received message from group: %u\n", src_addr.nl_groups);
- printf("Message: %s\n", msg.data);
- }
- }
- int main() {
- int sock_fd;
- uint32_t groups = MULTICAST_GROUP1; // 初始订阅组
- if (init_netlink_socket(&sock_fd, groups) < 0) {
- return -1;
- }
- // 动态加入组2
- join_multicast_group(sock_fd, MULTICAST_GROUP2);
- printf("Listening for multicast messages...\n");
- receive_messages(sock_fd);
- // 动态退出组2
- leave_multicast_group(sock_fd, MULTICAST_GROUP2);
- close(sock_fd);
- return 0;
- }
复制代码 总结
通过以上步调,内核态可以发送Netlink多播组消息,用户态可以接收并处理这些消息,同时支持动态加入和退出多播组的功能。本文提供的代码可以用于实际开发中,资助实现高效的内核态与用户态通信。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |