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

相关推荐
如意.7592 小时前
【Linux开发工具实战】Git、GDB与CGDB从入门到精通
linux·运维·git
Thera7773 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ4 小时前
Linux 查询某进程文件所在路径 命令
linux·运维·服务器
逐步前行4 小时前
STM32_TIM_寄存器操作
stm32·单片机·嵌入式硬件
0南城逆流05 小时前
【STM32】知识点介绍七:PWM功能
stm32·单片机·嵌入式硬件
智者知已应修善业5 小时前
【51单片机独立按键控制数码管移动反向,2片74CH573/74CH273段和位,按键按下保持原状态】2023-3-25
经验分享·笔记·单片机·嵌入式硬件·算法·51单片机
安当加密5 小时前
无需改 PAM!轻量级 RADIUS + ASP身份认证系统 实现 Linux 登录双因子认证
linux·运维·服务器
内卷焦虑人士6 小时前
Windows安装WSL2+Ubuntu 22.04
linux·windows·ubuntu
我是一棵无人问荆的小草6 小时前
单片机通电后延迟启动策略
单片机·嵌入式硬件
日更嵌入式的打工仔7 小时前
UART RX为什么要上拉
单片机