zoukankan      html  css  js  c++  java
  • netlink

    netlink的特点

    netlink提供了一种在用户态和内核态之间进行数据传递的方式;

    (1) 是一种异步的通信机制,传递的数据会放在socket的缓存队列中;

    (2) 内核可以主动发送数据给用户空间;

    (3) 能够在内核模块中使用;

    (4) 支持组播;

    (5) 使用套接字编程;

    测试例程
    用户态例程
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <unistd.h>
     5 #include <sys/socket.h>
     6 #include <linux/netlink.h>
     7 
     8 #define MAX_PAYLOAD 64
     9 
    10 #define NETLINK_TEST 25
    11 
    12 int main(int argc, char * argv[])
    13 {
    14     int sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST);
    15     if (sock_fd < 0) {
    16         perror("create socket failed!
    ");
    17         return -1;
    18     }
    19 
    20     struct sockaddr_nl src_addr;
    21     memset(&src_addr, 0, sizeof(struct sockaddr_nl));
    22     src_addr.nl_family = AF_NETLINK;
    23     src_addr.nl_pid = getpid();
    24     src_addr.nl_groups = 0;
    25 
    26     if (bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(struct sockaddr)) < 0) {
    27         perror("bind socket failed!
    ");
    28         close (sock_fd);
    29         return -1;
    30     }
    31 
    32     struct sockaddr_nl dest_addr;
    33 
    34     memset(&dest_addr, 0, sizeof(struct sockaddr_nl));
    35     dest_addr.nl_family = AF_NETLINK;
    36     dest_addr.nl_pid = 0;
    37     dest_addr.nl_groups = 0;
    38     
    39     struct nlmsghdr *nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
    40     if (nlh == NULL) {
    41         perror("malloc nlmsghdr failed!
    ");
    42         close(sock_fd);
    43         return -1;
    44     }
    45 
    46     memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
    47     nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
    48     nlh->nlmsg_pid = getpid();
    49     nlh->nlmsg_flags = 0;
    50 
    51     strcpy(NLMSG_DATA(nlh), "Hello kernel!");
    52 
    53     struct iovec iov;
    54     iov.iov_base = (void *)nlh;
    55     iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
    56 
    57     struct msghdr msg;
    58     memset(&msg, 0, sizeof(struct msghdr));
    59     msg.msg_name = (void *)&dest_addr;
    60     msg.msg_namelen = sizeof(struct sockaddr_nl);
    61     msg.msg_iov = &iov;
    62     msg.msg_iovlen = 1;
    63 
    64     if (sendmsg(sock_fd, &msg, 0) < 0) {
    65         perror("send msg failed!
    ");
    66         free(nlh);
    67         close(sock_fd);
    68         return -1;
    69     }
    70 
    71     printf("send msg: %s
    ", (char *)NLMSG_DATA(nlh));
    72 
    73     memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
    74     
    75     if (recvmsg(sock_fd, &msg, 0) < 0) {
    76         perror("recv msg failed!
    ");
    77         free(nlh);
    78         close(sock_fd);
    79         return -1;
    80     }
    81         
    82     printf("receive msg: %s
    ", (char *)NLMSG_DATA(nlh));
    83 
    84 
    85     free(nlh);
    86     close(sock_fd);
    87 
    88     return 0;
    89 }
    内核态例程
     1 #include <linux/init.h>
     2 #include <linux/module.h>
     3 #include <net/sock.h>
     4 #include <net/netlink.h>
     5 #include <linux/string.h>
     6 
     7 #define NETLINK_TEST 25
     8 #define MAX_MSGSIZE 64
     9 
    10 static struct sock *nl_sock = NULL;
    11 
    12 static void send_msg(char *msg, int pid)
    13 {
    14     struct sk_buff *skb = NULL;
    15     struct nlmsghdr *nlh = NULL;
    16     int msglen = strlen(msg);
    17 
    18     if (msg == NULL || nl_sock == NULL) {
    19         return;
    20     }
    21 
    22     skb = alloc_skb(NLMSG_SPACE(MAX_MSGSIZE), GFP_KERNEL);
    23     if (skb == NULL) {
    24         printk(KERN_ERR "allock skb failed!
    ");
    25         return;
    26     }
    27 
    28     nlh = nlmsg_put(skb, 0, 0, 0, MAX_MSGSIZE, 0);
    29     NETLINK_CB(skb).portid = 0;
    30     NETLINK_CB(skb).dst_group = 0;
    31     memcpy(NLMSG_DATA(nlh), msg, msglen + 1);
    32 
    33     printk("send msg: %s
    ", (char *)NLMSG_DATA(nlh));
    34 
    35     netlink_unicast(nl_sock, skb, pid, MSG_DONTWAIT);
    36 }
    37 
    38 static void recv_msg(struct sk_buff *in_skb)
    39 {
    40     struct sk_buff *skb = NULL;    
    41     struct nlmsghdr *nlh = NULL;
    42 
    43     skb = skb_get(in_skb);
    44     if (skb->len >= nlmsg_total_size(0)) {
    45         nlh = nlmsg_hdr(skb);
    46 
    47         printk("receive msg: %s
    ", (char *)NLMSG_DATA(nlh));
    48         
    49         send_msg("Hello app!", nlh->nlmsg_pid);
    50 
    51         kfree_skb(skb);
    52     }
    53 }
    54 
    55 static int netlink_init(void)
    56 {
    57     struct netlink_kernel_cfg netlink_cfg;
    58     memset(&netlink_cfg, 0, sizeof(struct netlink_kernel_cfg));
    59     netlink_cfg.input = recv_msg;
    60 
    61     nl_sock = netlink_kernel_create(&init_net, NETLINK_TEST, &netlink_cfg);
    62     if (nl_sock == NULL) {
    63         printk(KERN_ERR "netlink: netlink_kernel_create failed!
    ");
    64         return -1;
    65     }
    66     
    67     printk("netlink: netlink module init success!
    ");
    68     return 0;
    69 }
    70 
    71 static void netlink_exit(void)
    72 {
    73     if (nl_sock != NULL) {
    74         sock_release(nl_sock->sk_socket);
    75     }
    76 
    77     printk("netlink: netlink module exit success!
    ");
    78 }
    79 
    80 module_init(netlink_init);
    81 module_exit(netlink_exit);
    82 MODULE_LICENSE("GPL");

    Makefile

     1 ifneq ($(KERNELRELEASE),)
     2     obj-m :=netlink_kernel.o
     3 else
     4     KERNELDIR ?=/lib/modules/$(shell uname -r)/build
     5     PWD :=$(shell pwd)
     6 default:
     7     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
     8 clean:
     9     rm -rf *.o *.mod.c *.ko *.symvers *.order *.makers
    10 endif
    测试结果

    用户态:

    1 [root@localhost netlink]# ./netlink_app 
    2 send msg: Hello kernel!
    3 receive msg: Hello app!

    内核态:

    1 [root@localhost netlink]# insmod netlink_kernel.ko
    2 [root@localhost netlink]# cat /proc/kmsg 
    3 <4>[19211.917913] receive msg: Hello kernel!
    4 <4>[19211.917916] send msg: Hello app!

    本文参考:

    http://blog.chinaunix.net/uid-28541347-id-5578403.html

    http://blog.csdn.net/ganshuyu/article/details/30241313

  • 相关阅读:
    数据恢复
    InnoDB LRU优化
    STM32 M0之SPI
    C# 添加日志文件
    VCI_CAN二次开发摘机
    [一点感触]ADF4350 ADF4111混频记
    Linux札记
    C# String与Byte数组的转换
    STM32 CAN
    stm32 F40x CCM数据区的使用
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11755436.html
Copyright © 2011-2022 走看看