摘要
本文通过一个简单的例子介绍了Netlink机制的使用,展示了内核态与用户态之间的异步通信。主要流程包括:内核态驱动注册Netlink用户自定义消息组,用户态程序通过写入字符设备将PID发送给内核态驱动,内核态使用Netlink单播或广播机制通知对应的PID,用户态收到消息后打印出来自内核的信息。
背景
netlink是内核中常用的机制,可以使内核态主动通知用户态并且是异步的操作。本文实现了一个简单的例子介绍netlink的使用机制。主要流程是:内核态驱动注册netlink用户自定义消息组,然后用户态程序通过write字符设备将pid发送给内核态驱动,内核态然后使用netlink单播/广播机制通知到对应的pid,然后用户态收到消息后打印出来自内核的消息
代码与主要流程
内核态程序 test.c
主要流程:
初始化的时候通过netlink_kernel_create创建netlink的用户自定义的netlink消息组。
然后创建字符设备至此写入和ioctl。写入是指定pid,ioctl是触发发送到用户态的netlink中去。
通过nlmsg_new创建一个sk_buffer
然后nlmsg_put初始化skb
然后将需要传送的消息拷贝到mlh的data域段并且设置mlh的msg len(如果不设置,用户态收到的该部分信息不对)
然后调用netlink_unicast单播到某个pid,指定创建的netlink的自定义消息组句柄、需要传送的skb、用户pid、以及flag。也可以组播,组播需要把netlink_unicast换成netlink_broadcast。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <net/netlink.h>
#include <net/net_namespace.h>
#define NETLINK_USER 31
#define DEVICE_NAME "netlink_device"
#define CLASS_NAME "nlclass"
#define IOCTL_CMD 0x12345678 // Must match the command in the user program
static struct sock *nl_sk = NULL;
static dev_t dev_num;
static struct cdev c_dev;
static struct class *cl;
static int user_pid = 0; // Store the user space process PID
static void send_to_user(void) {
struct sk_buff *skb;
char msg[] = "Hello from kernel!";
int size = NLMSG_SPACE(strlen(msg) + 1); // including null terminator
if (user_pid == 0) {
printk(KERN_ERR "User PID not set\n");
return;
}
skb = nlmsg_new(size, GFP_KERNEL);
if (!skb) {
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
struct nlmsghdr *nlh = nlmsg_put(skb, 0, 0, NLMSG_DONE, strlen(msg) + 1, 0);
if (!nlh) {
nlmsg_free(skb);
printk(KERN_ERR "Failed to put nlmsghdr\n");
return;
}
memcpy(NLMSG_DATA(nlh), msg, strlen(

最低0.47元/天 解锁文章
1105

被折叠的 条评论
为什么被折叠?



