内核和用户态异步通信实例(netlink)

| 2009年5月16日

内核版本:2.6.26

内核态程序:knetlink.c

/*
 * Copyright (c) 2009-~ Helight.Xu
 *
 * This source code is released for free distribution under the terms of the
 * GNU General Public License
 *
 * Author:       Helight.Xu<Helight.Xu@gmail.com>
 * Created Time: Sat 16 May 2009 04:20:14 PM CST
 * File Name:    knetlink.c
 *
 * Description:  
 */

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

#define NETLINK_XUX           21       /* testing */  
#define VFW_GROUP  1
#define MSG_SIZE NLMSG_SPACE(2048)

static struct sock *xux_sock;

struct netlink_data{
        struct nlmsghdr msg;
        char data[1024];
};

static void test_link(struct sk_buff *skb)
{
        struct nlmsghdr *nlh;
        u32             rlen;
        void            *data;

         while (skb->len >= NLMSG_SPACE(0)) {
                nlh = nlmsg_hdr(skb);
                if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
                        return;
                rlen = NLMSG_ALIGN(nlh->nlmsg_len);
                if (rlen > skb->len)
                        rlen = skb->len;
                data = NLMSG_DATA(nlh);
                printk("link:%s", (char *)data);
                netlink_ack(skb, nlh, 0);
                skb_pull(skb, rlen);
        }
}

int __init init_link(void)
{
        xux_sock = netlink_kernel_create(&init_net, NETLINK_XUX, 0,
                                           test_link, NULL, THIS_MODULE);
        if (!xux_sock){
                printk("cannot initialize netlink socket");
                return -1;
        } else
                xux_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;


        printk("Init OK!\n");
        return 0;
}

void __exit exit_link(void)
{
        netlink_kernel_release(xux_sock);
        printk(": Release OK!\n");
        return;
}

MODULE_AUTHOR("Helight.Xu");
MODULE_LICENSE("Dual BSD/GPL");
module_init(init_link);
module_exit(exit_link);

用户态程序:unetlink.c

/*
 * Copyright (c) 2009-~ Helight.Xu
 *
 * This source code is released for free distribution under the terms of the
 * GNU General Public License
 *
 * Author:       Helight.Xu<Helight.Xu@gmail.com>
 * Created Time: Sat 16 May 2009 04:20:14 PM CST
 * File Name:    unetlink.c
 *
 * Description:  
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>

#define NETLINK_XUX           21       /* testing */  
#define VFW_GROUP  1

struct netlink_data{
        struct nlmsghdr msg;
        char data[1024];
};

int link_open(void);

int main(int args, char *argv[])
{
        struct netlink_data nldata;
        struct nlmsghdr *msg = &nldata.msg;
        int retval;
        struct sockaddr_nl addr;
        char *data = "hello world!\0";
        int size = strlen(data);

        int fd = link_open();

        memset(&nldata, '\0', sizeof(nldata));
        msg->nlmsg_len = NLMSG_SPACE(size);
        msg->nlmsg_type = 0;
        msg->nlmsg_flags = 0;
        msg->nlmsg_seq = 0;
        addr.nl_family = AF_NETLINK;
        addr.nl_pid = 0;
        addr.nl_groups = 0;

        memcpy(NLMSG_DATA(msg), data, size);

        retval = sendto(fd, &nldata, msg->nlmsg_len, 0,
                        (struct sockaddr*)&addr, sizeof(addr));

        printf("hello:%02x len: %d  data:%s\n",
                        NLMSG_DATA(msg),
                        sizeof(NLMSG_DATA(msg)),
                        NLMSG_DATA(msg));
        close(fd);
        return 0;
}

int link_open(void)
{
        int saved_errno;
        int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_XUX);

        if (fd < 0) {
                saved_errno = errno;
                if (errno == EINVAL || errno == EPROTONOSUPPORT ||
                                errno == EAFNOSUPPORT)
                        printf("Error - audit support not in kernel");
                else
                        printf("Error opening audit netlink socket (%s)",
                                strerror(errno));
                errno = saved_errno;
                return fd;
        }
        if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
                saved_errno = errno;
                close(fd);
                        printf("Error setting audit netlink socket CLOEXEC flag (%s)",
                        strerror(errno));
                errno = saved_errno;
                return -1;
        }
        return fd;
}

测试结果:

xux@zhwen:~/netdev$ sudo insmod knetlink.ko
xux@zhwen:~/netdev$ ./unetlink
[ 2373.160357] Init OK!
[ 2378.000012] link:hello world!
xux@zhwen:~/netdev$ 
看完本文有收获?请分享给更多人

关注「黑光技术」,关注大数据+微服务