下面是一个简单的示例代码,演示了如何从内核模块向用户空间应用程序发送数据。

内核模块代码:

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

#define NETLINK_USER 31

struct sock *netlink_sock = NULL;

static void netlink_recv_msg(struct sk_buff *skb)
{
    struct nlmsghdr *nlh;
    int pid, len;
    void *msg_data;
    char *reply = 'Hello from kernel!';

    nlh = (struct nlmsghdr *)skb->data;
    pid = nlh->nlmsg_pid; /* 发送进程的 pid */

    len = nlh->nlmsg_len - NLMSG_HDRLEN;
    if (len > 0) {
        msg_data = NLMSG_DATA(nlh);
        printk(KERN_INFO 'Received data from user: %s\n', (char *)msg_data);
    }

    /* 发送回复消息给用户 */
    struct sk_buff *skb_out;
    int msg_size = strlen(reply) + 1;
    int res;

    skb_out = nlmsg_new(msg_size, 0);
    if (!skb_out) {
        printk(KERN_ERR 'Failed to allocate new skb\n');
        return;
    }

    nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
    NETLINK_CB(skb_out).dst_group = 0;

    strncpy(nlmsg_data(nlh), reply, msg_size);

    res = nlmsg_unicast(netlink_sock, skb_out, pid);
    if (res < 0)
        printk(KERN_ERR 'Error sending reply to user\n');
}

static struct netlink_kernel_cfg netlink_cfg = {
    .input = netlink_recv_msg,
};

static int __init netlink_init(void)
{
    netlink_sock = netlink_kernel_create(&init_net, NETLINK_USER, &netlink_cfg);
    if (!netlink_sock) {
        printk(KERN_ERR 'Failed to create netlink socket\n');
        return -ENOMEM;
    }

    printk(KERN_INFO 'Netlink socket created\n');
    return 0;
}

static void __exit netlink_exit(void)
{
    if (netlink_sock)
        netlink_kernel_release(netlink_sock);

    printk(KERN_INFO 'Netlink socket released\n');
}

module_init(netlink_init);
module_exit(netlink_exit);
MODULE_LICENSE('GPL');

应用程序代码:

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

#define NETLINK_USER 31

int main(int argc, char **argv)
{
    int sockfd;
    struct sockaddr_nl src_addr, dest_addr;
    struct nlmsghdr *nlh;
    struct iovec iov;
    struct msghdr msg;
    char *msg_data = 'Hello from user!';
    char buf[4096];

    sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_USER);
    if (sockfd < 0) {
        perror('socket');
        exit(EXIT_FAILURE);
    }

    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.nl_family = AF_NETLINK;
    src_addr.nl_pid = getpid();

    bind(sockfd, (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(strlen(msg_data) + 1));
    nlh->nlmsg_len = NLMSG_SPACE(strlen(msg_data) + 1);
    nlh->nlmsg_pid = getpid();
    nlh->nlmsg_flags = 0;

    strcpy(NLMSG_DATA(nlh), msg_data);

    iov.iov_base = (void *)nlh;
    iov.iov_len = nlh->nlmsg_len;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = (void *)&dest_addr;
    msg.msg_namelen = sizeof(dest_addr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    sendmsg(sockfd, &msg, 0);

    /* 接收来自内核的回复消息 */
    memset(buf, 0, sizeof(buf));
    recv(sockfd, &buf, sizeof(buf), 0);
    printf('Received reply from kernel: %s\n', buf);

    close(sockfd);
    return 0;
}

运行应用程序,输出应该类似于以下内容:

Received reply from kernel: Hello from kernel!
Linux Netlink: 从内核模块发送数据到应用程序示例代码

原文地址: https://www.cveoy.top/t/topic/nu3b 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录