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

相关推荐
xiugou79813 分钟前
记录一下CubeMX+Clion的STM32 CMake工程中如何修改Flash程序存储的起始地址
stm32·单片机·嵌入式硬件
青草地溪水旁15 分钟前
Linux 高性能 I/O 事件通知机制的核心系统调用—— `epoll_ctl`
linux·c语言·c++
不会c嘎嘎16 分钟前
Linux -- 基于TCP服务器实现一个简单的电商网站
linux·服务器·tcp/ip
程序leo源16 分钟前
Linux_基础指令(二)
android·linux·运维·服务器·青少年编程
君宝1 小时前
Linux ALSA架构:PCM_OPEN流程 (二)
java·linux·c++
葵花日记1 小时前
LINUX--编译器gcc/g++
linux·运维·服务器
csdn_aspnet2 小时前
Linux Node.js 安装及环境配置详细教程
linux·node.js
PAQQ3 小时前
解决 ubuntu 重启串口号变化
linux·运维·ubuntu
dyxal3 小时前
linux系统安装wps
linux·运维·wps
大家的笔记本3 小时前
jetson orin super nano(arm linux系统)上读取大恒图像工业相机(型号MER-050-560U3C)教程
linux·arm开发·相机