当前位置: 首页 > news >正文

linux netlink实现用户态和内核态数据交互

1,内核态代码

#include <linux/module.h>
#include <linux/netlink.h>
#include <net/sock.h>

#define NETLINK_TEST 31

struct sock *nl_sk = NULL;

static void nl_recv_msg(struct sk_buff *skb) {
    struct nlmsghdr *nlh;
    int pid;
    char *msg;
    
    nlh = (struct nlmsghdr*)skb->data;
    pid = nlh->nlmsg_pid; // 获取发送者的 PID
    msg = nlh->nlmsg_data;

    printk(KERN_INFO "Received message: %s from pid: %d\n", msg, pid);

    // 回复用户空间
    nlh->nlmsg_pid = 0; // 目标为用户空间
    nlh->nlmsg_type = NLMSG_DONE; // 消息类型
    strcpy(nlh->nlmsg_data, "Hello from Kernel");
    
    netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
}

static int __init hello_init(void) {
    struct netlink_kernel_cfg cfg = {
        .input = nl_recv_msg,
    };

    nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &cfg);
    if (!nl_sk) {
        printk(KERN_ALERT "Error creating netlink socket.\n");
        return -ENOMEM;
    }
    printk(KERN_INFO "Netlink module initialized.\n");
    return 0;
}

static void __exit hello_exit(void) {
    netlink_kernel_release(nl_sk);
    printk(KERN_INFO "Netlink module exited.\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

运行insmod hello.ko

3,用户态代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>

#define NETLINK_TEST 31

int main() {
    struct sockaddr_nl src_addr, dest_addr;
    struct nlmsghdr *nlh = NULL;
    int sock_fd, msg_size;
    char *msg = "Hello from User";

    sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
    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(); // 用于识别

    bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr));

    memset(&dest_addr, 0, sizeof(dest_addr));
    dest_addr.nl_family = AF_NETLINK;
    dest_addr.nl_pid = 0; // 目标为内核
    dest_addr.nl_groups = 0;

    nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(1024));
    nlh->nlmsg_len = NLMSG_LENGTH(strlen(msg) + 1);
    nlh->nlmsg_pid = getpid();
    nlh->nlmsg_flags = 0;
    strcpy(NLMSG_DATA(nlh), msg);

    msg_size = sendto(sock_fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
    if (msg_size < 0) {
        perror("sendto");
        return -1;
    }

    // 接收内核的回复
    recv(sock_fd, nlh, NLMSG_BUFFER_SIZE, 0);
    printf("Received from kernel: %s\n", (char *)NLMSG_DATA(nlh));

    close(sock_fd);
    return 0;
}

gcc main.c -o main

 

相关文章:

  • 什么是多租户系统
  • 实战探讨:为什么 Redis Zset 选择跳表?
  • UDP / TCP 协议
  • 机器学习入门-线性回归模型/损失函数/梯度下降
  • Java SE(7)——类和对象(二)
  • 深入解析 SqlSugar 与泛型封装:实现通用数据访问层
  • 4.29-4.30 Maven+单元测试
  • Spring MVC @RequestBody 注解怎么用?接收什么格式的数据?
  • 数据赋能(208)——质量管理——及时性原则
  • 单细胞测序数据分析流程的最佳实践
  • 旋转矩阵公式理解
  • Learning vtkjs之PolyDataNormals
  • Android Compose 中 Side Effects 和 State 相关的 API 使用
  • Python datetime库的用法 Python从入门到入土系列第3篇-洞察标准库DateTime
  • 第九章:反击的序曲(续)
  • 优化01-统计信息
  • Space Engineers 太空工程师 [DLC 解锁] [Steam] [Windows]
  • 生成器模式(Builder Pattern)
  • C++ 单例模式详解
  • 智能决策支持系统的基本概念与理论体系
  • 是谁提议特朗普向好莱坞征税?
  • 41年轮回,从洛杉矶奔向洛杉矶,李宁故地重游再出发
  • 胡塞武装称以色列所有机场均为其打击目标
  • 局势紧张之际,伊朗外长下周访问巴基斯坦和印度
  • 多地晒五一假期前两日成绩单,湖南单日客流同比增长逾三成
  • 党旗下的青春|赵天益:少年确定志向,把最好的时光奉献给戏剧事业