linux内核netlink 程序编写及参考资料

内核态

#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 <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 struct sock *netlinkfd = 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);//创建len大小的struct sk_buff并返回
    if(!nl_skb)
    {
        printk("netlink_alloc_skb error\n");
        return -1;
    }
    nlh = nlmsg_put(nl_skb, 0, 0, USER_MSG, len, 0);//-将一个新的netlink消息加入到skb中。如果skb无法存放消息则返回NULL。
    if(nlh == NULL)
    {
        printk("nlmsg_put() error\n");
        nlmsg_free(nl_skb);//释放nlmsg_new()创建的skb。
        return -1;
    }
    memcpy(nlmsg_data(nlh), pbuf, len);//把要发送的数据的len长度COPY给struct nlmsghdr *nlh 
    ret = netlink_unicast(netlinkfd, nl_skb, USER_PORT, MSG_DONTWAIT);//单播信息
	return ret;
}
static void recv_cb(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);//从sk_buff(->data)获取struct nlmsghdr数据结构 
        data = NLMSG_DATA(nlh);//用于取得消息的数据部分的首地址
        if(data)
        {
            printk("kernel receive data: %s\n", (int8_t *)data);
            send_msg(data, nlmsg_len(nlh));//后一个参数应该是消息的长度
        }
    }
} 
struct netlink_kernel_cfg cfg = 
{
    .input = recv_cb,//接收到信息时的回调函数
};
static int __init test_netlink_init(void)
{
    printk("init netlink_demo!\n");
    netlinkfd = netlink_kernel_create(&init_net, USER_MSG, &cfg);//创建套接字
    if(!netlinkfd)
    {
        printk(KERN_ERR "can not create a netlink socket!\n");
        return -1;
    }
    printk("netlink demo init ok!\n");
    return 0;
}
static void __exit test_netlink_exit(void)
{
    sock_release(netlinkfd->sk_socket);
    printk(KERN_DEBUG "netlink exit\n!");
}
module_init(test_netlink_init);
module_exit(test_netlink_exit);

用户态

/*******************************
file:           u_netlink.c
description:    netlink demo
author:         arvik
email:          1216601195@qq.com
blog:           http://blog.csdn.net/u012819339
*******************************/
#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(int argc, char **argv)
{
    char *data = "hello kernel";
    struct sockaddr_nl  local, dest_addr;

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

    skfd = socket(AF_NETLINK, SOCK_RAW, USER_MSG);
    if(skfd == -1)
    {
        printf("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)
    {
        printf("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; // to kernel
    dest_addr.nl_groups = 0;

    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; //self port

    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)
    {
        perror("sendto error1\n");
        close(skfd);
        exit(-1);
    }
    printf("wait kernel msg!\n");
    memset(&info, 0, sizeof(info));
    ret = recvfrom(skfd, &info, sizeof(struct _my_msg), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
    if(!ret)
    {
        perror("recv form kernel error\n");
        close(skfd);
        exit(-1);
    }

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

    free((void *)nlh);
    return 0;

}


makefile可参考:https://blog.csdn.net/dj_jeck/article/details/79843189
https://www.cnblogs.com/lilto/p/11878303.html

代码来源:https://blog.csdn.net/u012819339/article/details/51334600?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param
参考资料:
https://blog.csdn.net/zllbuaa/article/details/30786729
https://www.cnblogs.com/arnoldlu/p/9532254.html

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值