ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux 内核态与用户态通信 netlink

2019-03-08 10:51:39  阅读:745  来源: 互联网

标签:netlink nl struct 内核 Linux test nlh include


参考资料:

https://blog.csdn.net/zqixiao_09/article/details/77131283

 

 

 

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


#define NETLINK_USER 22
#define USER_MSG (NETLINK_USER + 1)
#define USER_PORT 50


MODULE_LICENSE("GPL");
MODULE_AUTHOR("arvik");
MODULE_DESCRIPTION("netlink_demo");

static void test_netlink_rcv(struct sk_buff *skb);

struct netlink_kernel_cfg cfg = {
    .input = test_netlink_rcv,
    /*...*/
};
static struct sock *test_netlink_sock = NULL;

int send_msg(int8_t *pbuf, uint16_t len)
{
    struct sk_buff *nl_skb;
    struct nlmsghdr *nlh;

    int ret;

    nl_skb = nlmsg_new(len, GFP_ATOMIC);
    if (!nl_skb) {
        printk("netlink_alloc_skb error\n");
        return -1;
    }
    /*将header填充到skb中*/
    nlh = nlmsg_put(nl_skb, 0, 0, USER_MSG, len, 0);
    if (nlh == NULL) {
        printk("put error\n");
        nlmsg_free(nl_skb);
        return -1;
    }
    /*拷贝data*/
    memcpy(nlmsg_data(nlh), pbuf, len);

    /*发送*/
    ret = netlink_unicast(test_netlink_sock, nl_skb, USER_PORT, MSG_DONTWAIT);

    return ret;
}

static void test_netlink_rcv(struct sk_buff *skb)
{
    struct nlmsghdr *nlh = NULL;

    void *data = NULL;

    printk("skb->len %u\n", skb->len);
    if (skb->len >= nlmsg_total_size(0))
    {
        nlh = nlmsg_hdr(skb);
        data = NLMSG_DATA(nlh);
        if (data) {
            printk("kernel receive date : %s\n", (int8_t *)data);
            send_msg(data, nlmsg_len(nlh));
        }
    }
}


static int __init test_netlink_init(void)
{
    printk("test netlink init\n");

    test_netlink_sock = netlink_kernel_create(&init_net, USER_MSG, &cfg);    
    if (test_netlink_sock == NULL) {
        printk("test netlink init error\n");
        return -1;
    }

    printk("test netlink init ok\n");
    
    return 0;
}
static void __exit test_netlink_exit(void)
{
    netlink_kernel_release(test_netlink_sock);
    test_netlink_sock = NULL;

    printk("test netlink exit\n");
}

module_init(test_netlink_init);
module_exit(test_netlink_exit);

 

 

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

#define NETLINK_USER 22
#define USER_MSG (NETLINK_USER + 1)

#define MSG_LEN 100

#define MAX_PLOAD 100

struct _my_msg {
    struct nlmsghdr hdr;
    int8_t data[MSG_LEN];
};

int main()
{
    char *data = "hello kernel";
    socklen_t addr_len;
    struct sockaddr_nl local, dest_addr;

    int skfd;
    struct nlmsghdr *nlh = NULL;
    struct _my_msg info;
    int ret;

    //创建socket
    skfd = socket(AF_NETLINK, SOCK_RAW, USER_MSG);
    if (skfd == (-1)) {
        fprintf(stderr, "create socket error...%s\n", strerror(errno));
        return (-1);
    }

    /*绑定*/
    memset(&local, 0, sizeof(local));
    local.nl_family =  AF_NETLINK;
    local.nl_pid = 50;
    local.nl_groups = 0;
    if (bind(skfd, (struct sockaddr *)&local, sizeof(local)) != 0) {
        fprintf(stderr, "bind error\n");
        close(skfd);
        return (-1);
    }

    //初始化目的地址
    memset(&dest_addr, 0, sizeof(dest_addr));
    dest_addr.nl_family = AF_NETLINK; 
    dest_addr.nl_pid = 0;
    dest_addr.nl_groups = 0;
    /*填写data*/
    nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD));
    memset(nlh, 0, sizeof(struct nlmsghdr));
    nlh->nlmsg_len = NLMSG_SPACE(MAX_PLOAD);
    nlh->nlmsg_flags = 0;
    nlh->nlmsg_type = 0;
    nlh->nlmsg_seq = 0;
    nlh->nlmsg_pid = local.nl_pid;
    
    memcpy(NLMSG_DATA(nlh), data, strlen(data));
    ret = sendto(skfd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_nl));
    if (ret < 0) {
//        fprintf(stderr, "sendto error\n");
        perror("sendto error: ");
        close(skfd);
        return (-1);
    }

    printf("wait kernel msg!\n");
    memset(&info, 0, sizeof(info));

    /*接受信息*/
    ret = recvfrom(skfd, &info, sizeof(struct _my_msg), 0, (struct sockaddr *)&dest_addr, &addr_len);
    if (ret <= 0) {
//        fprintf(stderr, "recv from kernel  error\n");
        perror("recv from kernel error: ");
        close(skfd);
        return (-1);
    }

    printf("msg receive from kernel : %s\n", info.data);
    close(skfd);

    free((void *)nlh);

    close(skfd);

    return 0;
}

 

标签:netlink,nl,struct,内核,Linux,test,nlh,include
来源: https://www.cnblogs.com/rivsidn/p/10493954.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有