zoukankan      html  css  js  c++  java
  • netlink组播的使用

    Linux的netlink机制是非常好的Linux内核与应用层进行双向交互数据的方式。其常用的单播方式可以实现内核为服务端,应用层为客户端的通信方式。如果需要实现应用层为服务端,内核为客户端的通信方式,则需要使用组播。这种场景一般是应用层守护进程需要实现获取内核的某些模块的状态信息。

    内核中已经定义好的组有:

    #define NETLINK_ROUTE           0       /* Routing/device hook                          */
    #define NETLINK_W1 1 /* 1-wire subsystem */
    #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
    #define NETLINK_FIREWALL 3 /* Firewalling hook */
    #define NETLINK_INET_DIAG 4 /* INET socket monitoring */
    #define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
    #define NETLINK_XFRM 6 /* ipsec */
    #define NETLINK_SELINUX 7 /* SELinux event notifications */
    #define NETLINK_ISCSI 8 /* Open-iSCSI */
    #define NETLINK_AUDIT 9 /* auditing */
    #define NETLINK_FIB_LOOKUP 10
    #define NETLINK_CONNECTOR 11
    #define NETLINK_NETFILTER 12 /* netfilter subsystem */
    #define NETLINK_IP6_FW 13
    #define NETLINK_DNRTMSG 14 /* DECnet routing messages */
    #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
    #define NETLINK_GENERIC 16

    内核代码:

     1 #include <linux/module.h>
     2 #include <linux/kernel.h>
     3 #include <linux/init.h>
     4 #include <net/sock.h>
     5 #include <linux/socket.h>
     6 #include <linux/net.h>
     7 #include <asm/types.h>
     8 #include <linux/netlink.h>
     9 #include <linux/rtnetlink.h>
    10 #include <linux/skbuff.h>
    11 #include <linux/delay.h>
    12 
    13 #define NETLINK_USER 29  //User defined group, consistent in both kernel prog and user prog
    14 #define MYGRP 2 //User defined group, consistent in both kernel prog and user prog
    15 
    16 struct sock *nl_sk = NULL;
    17 
    18 static void send_to_user(void);
    19 
    20 static void send_to_user(void)
    21 {
    22     struct sk_buff *skb_out;
    23     struct nlmsghdr *nlh;
    24     int msg_size;
    25     char msg[20] = "Hello from kernel";
    26     int res;
    27 
    28     printk(KERN_INFO "Entering: %s
    ", __FUNCTION__);
    29     msg_size = strlen(msg);
    30     printk(KERN_INFO "msg_size: %d
    ", msg_size);
    31     //msg[msg_size - 1] = '';
    32     skb_out = nlmsg_new(msg_size, 0);
    33 
    34     if (!skb_out) {
    35         printk(KERN_ERR "Failed to allocate new skb
    ");
    36         return;
    37     }
    38     nlh = nlmsg_put(skb_out, 0, 1, NLMSG_DONE, msg_size, 0);
    39     //NETLINK_CB(skb_out).dst_group = 1; /* Multicast to group 1, 1<<0 */
    40     strncpy(nlmsg_data(nlh), msg, msg_size);
    41 
    42     res = nlmsg_multicast(nl_sk, skb_out, 0, MYGRP, 0);
    43     if (res < 0) {
    44         printk(KERN_INFO "Error while sending bak to user, err id: %d
    ", res);
    45     }
    46 }
    47 
    48 static int __init
    49 hello_init(void) {
    50 
    51     struct netlink_kernel_cfg cfg = {
    52         .groups = MYGRP,
    53     };
    54     printk("Entering: %s
    ", __FUNCTION__);
    55     nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);
    56     if (!nl_sk) {
    57         printk(KERN_ALERT "Error creating socket.
    ");
    58         return -10;
    59     }
    60 
    61     msleep(10000);
    62     send_to_user();
    63 
    64     return 0;
    65 }
    66 
    67 static void __exit
    68 hello_exit(void) {
    69 
    70     printk(KERN_INFO "exiting hello module
    ");
    71     netlink_kernel_release(nl_sk);
    72 }
    73 
    74 module_init(hello_init);
    75 module_exit(hello_exit);
    76 MODULE_LICENSE("GPL");

    应用层代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 #include<sys/socket.h>
     5 #include<linux/netlink.h>
     6 #include<sys/types.h>
     7 #include<unistd.h>
     8 
     9 #define MYPROTO 29 //User defined group, consistent in both kernel prog and user prog
    10 #define MYMGRP 2 //User defined group, consistent in both kernel prog and user prog
    11 
    12 int open_netlink()
    13 {
    14     int sock = socket(AF_NETLINK,SOCK_RAW,MYPROTO);
    15     struct sockaddr_nl addr;
    16 
    17     memset((void *)&addr, 0, sizeof(addr));
    18 
    19     if (sock<0)
    20         return sock;
    21     addr.nl_family = AF_NETLINK;
    22     addr.nl_pid = getpid();
    23     addr.nl_groups = MYMGRP;
    24     if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0)
    25         return -1;
    26     return sock;
    27 }
    28 
    29 int read_event(int sock)
    30 {
    31     struct sockaddr_nl nladdr;
    32     struct msghdr msg;
    33     struct iovec iov[2];
    34     struct nlmsghdr nlh;
    35     char buffer[65536];
    36     int ret;
    37     iov[0].iov_base = (void *)&nlh;
    38     iov[0].iov_len = sizeof(nlh);
    39     iov[1].iov_base = (void *)buffer;
    40     iov[1].iov_len = sizeof(buffer);
    41     msg.msg_name = (void *)&(nladdr);
    42     msg.msg_namelen = sizeof(nladdr);
    43     msg.msg_iov = iov;
    44     msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]);
    45     ret=recvmsg(sock, &msg, 0);
    46     if (ret<0) {
    47         return ret;
    48     }
    49     printf("Received message payload: %s
    ", NLMSG_DATA(&nlh));
    50     char *a = NLMSG_DATA(&nlh);
    51     int i;
    52     printf("Recv Data:
    ");
    53     for(i = 0; i < 10; i++) {
    54         printf("%c", a[i]);
    55     }
    56     printf("
    ");
    57 }
    58 
    59 int main(int argc, char *argv[])
    60 {
    61     int nls = open_netlink();
    62     if (nls<0) {
    63         err(1,"netlink");
    64     }
    65 
    66     while (1)
    67         read_event(nls);
    68     return 0;
    69 }

    其中 协议类型与组号 内核要与应用层保持一致,且内核模块要先运行。

  • 相关阅读:
    不能访问windows installer服务
    clr/c++自定线程安全集合
    Electron-Vue工程初始化,以及需要掌握的相关知识
    Windows下启动.Net Core程序脚本
    Electron打包
    .Net Core入门与.Net需要注意的地方
    winfrom 点击按钮button弹框显示颜色集
    获取计算机的网卡及打印机信息
    winfrom 界面时间动态加载
    c# winfrom 界面设计
  • 原文地址:https://www.cnblogs.com/sinaxyz/p/4525208.html
Copyright © 2011-2022 走看看