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