1、Netlink socket的作用:
  Netlink socket 是一种Linux特有的socket,用于实现用户进程与内核进程之间通信的一种特殊的进程间通信方式(IPC) ,也是网络应用程序与内核通信的最常用的接口。
  Netlink 是一种在内核和用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就能使用 Netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 Netlink。

2、内核预定义的协议类型有:
  #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
  对于每一个netlink协议类型,能有多达 32多播组,每一个多播组用一个位表示,netlink 的多播特性使得发送消息给同一个组仅需要一次系统调用,因而对于需要多拨消息的应用而言,大大地降低了系统调用的次数。

3、Netlink应用举例:热插拔监控
  (本节内容来自:http://www.360doc.com/content/13/0213/22/7044580_265511495.shtml)
  SD卡、USB、网线等设备的使用过程中都可以热插拔。新的Linux内核使用udev代替了hotplug作为热拔插管理,虽然有udevd管理热拔插,但有时候我们还是需要在应用程序中检测热拔插事件以便快速地处理,比如在读写SD卡的时候拔下SD卡,那么需要立即检测出该情况,然后结束读写线程,防止VFS崩溃。Netlink是面向数据包的服务,为内核与用户层搭建了一个高速通道,是udev实现的基础。该工作方式是异步的,用户空间程序不必使用轮询等技术来检测热拔插事件。
①、内核空间:
  在内核中使用 uevent 事件通知用户空间。uevent首先在内核中调用 netlink_kernel_create()函数创建一个socket套接字,该函数原型在netlink.h有定义,其类型是表示往用户空间发送消息的NETLINK_KOBJECT_UEVENT,groups=1。由于uevent只往用户空间发送消息而不接受,因此其输入回调函数input和cb_mutex都设置为NULL。

    #include<linux/netlink.h>
struct sock * netlink_kernel_create(struct net *net, int unit, unsigned int groups,
void (*input)(struct sk_buff *skb),
struct mutex *cb_mutex,
struct module *module);
<lib/kobject_uevent.c>
ue_sk->sk = netlink_kernel_create(net,NETLINK_KOBJECT_UEVENT, 1, NULL, NULL, THIS_MODULE);

  当有事件发生的时候,调用 kobject_uevent()函数,实际上最终是调用
    netlink_broadcast_filtered(uevent_sock, skb, 0, 1, GFP_KERNEL, kobj_bcast_filter, kobj);
  完成广播任务。

②、用户空间:
  处于用户空间的程序使用标准的socket API:socket(), bind(), sendmsg(), recvmsg() 和 close() 就能非常容易地使用 netlink socket。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <asm/types.h>
//该头文件需要放在netlink.h前面防止编译出现__kernel_sa_family未定义
#include <sys/socket.h>
#include <linux/netlink.h>void MonitorNetlinkUevent()
{int sockfd;struct sockaddr_nl sa;int len;char buf[4096];struct iovec iov;struct msghdr msg;int i;memset(&sa,0,sizeof(sa));sa.nl_family=AF_NETLINK;sa.nl_groups=NETLINK_KOBJECT_UEVENT;sa.nl_pid = 0;//getpid(); both is ok//①、创建一个socket描述符sockfd=socket(AF_NETLINK,SOCK_RAW,NETLINK_KOBJECT_UEVENT);if(sockfd==-1)printf("socket creating failed:%s\n",strerror(errno));//②、将描述符绑定到接收地址,  函数 bind() 用于把一个打开的 netlink socket 和 netlink 源 socket 地址绑定在一起if(bind(sockfd,(struct sockaddr *)&sa,sizeof(sa))==-1)printf("bind error:%s\n",strerror(errno));memset(&msg,0,sizeof(msg));iov.iov_base=(void *)buf;iov.iov_len=sizeof(buf);msg.msg_name=(void *)&sa;msg.msg_namelen=sizeof(sa);msg.msg_iov=&iov;msg.msg_iovlen=1;//③开始接收ueventlen=recvmsg(sockfd,&msg,0);if(len<0)printf("receive error\n");else if(len<32||len>sizeof(buf))printf("invalid message");for(i=0;i<len;i++)if(*(buf+i)=='\0')buf[i]='\n';printf("received %d bytes\n%s\n",len,buf);
}int main(int argc,char **argv)
{MonitorNetlinkUevent();return 0;
}

  创建socket描述符的时候指定协议族为 AF_NETLINK 或者 PF_NETLINK, 套接字type选择 SOCK_RAW 或者 SOCK_DGRAM,Netlink协议并不区分这两种类型,第三个参数协议填充 NETLINK_KOBJECT_UEVENT表示接收内核uevent信息。接着就绑定该文件描述
符到sockadd_nl, 注意该结构体nl_groups是接收掩码,取~0是将接收所有来自内核的消息,我们接收热拔插只需要填NETLINK_KOBJECT_UEVENT即可。接下来调用recvmsg开始接收内核消息,recvmsg函数需要我们填充message报头,包括指定接收缓存等工作。该函数会阻塞直到有热拔插事件产生。

4、相对于系统调用,ioctl及proc文件系统Netlink 具有哪些好处?
(1)、为了使用Netlink,用户仅需要在 include/linux/netlink.h 中增加一个新类型的 netlink 协议定义即可。
  比如 #define NETLINK_MYTEST 17 然后,内核和用户态应用就能即时通过 socket API 使用该 netlink协议类型进行数据交换。但系统调用需要增加新的系统调用;ioctl 则需要增加设备或文件, 那需要不少代码;proc文件系统则需要在 proc 下添加新的文件或目录,那将使本来就混乱的 proc 更加混乱。
(2)、netlink是一种异步通信机制,在内核和用户态应用之间传递的消息保存在socket缓存队列中,发送消息只是把消息保存在接收者的socket的接收队列,而不必等待接收者收到消息,但系统调用和 ioctl 则是同步通信机制,如果传递的数据太长,将影响调度粒度。
(3)、使用 netlink 的内核部分能采用模块的方式实现,使用 netlink 的应用部分和内核部分没有编译时依赖,但系统调用就有依赖,而且新的系统调用的实现必须静态地连接到内核中,他无法在模块中实现,使用新系统调用的应用在编译时需要依赖内核。
(4)、netlink 支持多播,内核模块或应用能把消息多播给一个netlink组,属于该neilink 组的所有内核模块或应用都能接收到该消息,内核事件向用户态的通知机制就使用了这一特性,所有对内核事件感兴趣的应用都能收到该子系统发送的内核事件,在后面的文章中将介绍这一机制的使用。
(5)、内核能使用 netlink 首先发起会话,但系统调用和 ioctl 只能由用户应用发起调用。
(6)、netlink 使用标准的 socket API,因此非常容易使用,但系统调用和 ioctl则需要专门的培训才能使用。

Netlink的简介及使用方法相关推荐

  1. Database之SQL:SQL之over partition by开窗函数的简介、使用方法(求各班级内各自排名/求各班级内第一名/求各班级内分数递增和等案例解析)之详细攻略

    Database之SQL:SQL之over partition by开窗函数的简介.使用方法(求各班级内各自排名/求各班级内第一名/求各班级内分数递增和等案例解析)之详细攻略 目录 over part ...

  2. Python编程语言学习:包导入和模块搜索路径简介、使用方法之详细攻略

    Python编程语言学习:包导入和模块搜索路径简介.使用方法之详细攻略 目录 包导入和模块搜索路径简介 1.Pyhon搜索模块路径的机制 2.自定义配置搜索路径

  3. ML之ME/LF:机器学习之风控业务中常用模型评估指标PSI(人群偏移度指标)的的简介、使用方法、案例应用之详细攻略

    ML之ME/LF:机器学习之风控业务中常用模型评估指标PSI(人群偏移度指标)的的简介.使用方法.案例应用之详细攻略 目录 PSI(稳定度指标)的简介 1.如何计算PSI? (1).PSI计算过程

  4. Python编程学习:让函数更加灵活的*args和**kwargs(设计不同数量参数的函数)的简介、使用方法、经典案例之详细攻略

    Python编程学习:让函数更加灵活的*args和**kwargs(设计不同数量参数的函数)的简介.使用方法.经典案例之详细攻略 目录 *args和**kwargs(设计不同数量的参数函数)的简介 1 ...

  5. Python之 sklearn:sklearn.preprocessing中的StandardScaler函数的简介及使用方法之详细攻略

    Python之 sklearn:sklearn.preprocessing中的StandardScaler函数的简介及使用方法之详细攻略 目录 sklearn.preprocessing中的Stand ...

  6. Py之seaborn:数据可视化seaborn库(二)的组合图可视化之密度图/核密度图分布可视化、箱型图/散点图、小提琴图/散点图组合可视化的简介、使用方法之最强攻略(建议收藏)

    Py之seaborn:数据可视化seaborn库(二)的组合图可视化之密度图/核密度图分布可视化.箱型图/散点图.小提琴图/散点图组合可视化的简介.使用方法之最强攻略(建议收藏) 目录 二.组合图可视 ...

  7. Py之matplotlib.pyplot:matplotlib.pyplot的plt.legend函数的简介、使用方法之详细攻略

    Py之matplotlib.pyplot:matplotlib.pyplot的plt.legend函数的简介.使用方法之详细攻略 目录 matplotlib.pyplot的plt.legend函数的简 ...

  8. Python编程语言学习:sklearn.manifold的TSNE函数的简介、使用方法、代码实现之详细攻略

    Python编程语言学习:sklearn.manifold的TSNE函数的简介.使用方法.代码实现之详细攻略 目录 Manifold简介 TSNE简介-数据降维且可视化 TSNE使用方法 TSNE代码 ...

  9. Python语言学习之lambda:lambda函数的简介、使用方法、案例大全之详细攻略

    Python语言学习之lambda:lambda函数的简介.使用方法.案例大全之详细攻略 目录 lambda函数的简介 1.lambda匿名函数的格式 2.lambda函数特点 3.lambda函数与 ...

最新文章

  1. win命令安装 安装cmake_win10下VSCode+CMake+Clang+GCC环境搭建教程图解
  2. UVa(12821),MCMF
  3. Java网络编程:TCP实现聊天
  4. Emacs:报错:File error: Cannot open load file,cl-lib解决
  5. 开发Connext DDS传输插件不用求人,看这一篇就够了
  6. 大学生 生活小技巧:利用插件(Tampermonkey )学习网课 | 查题
  7. 瑞星搜狐畅游合作 “云安全”首次嵌入网游客户端
  8. ROVIO mobile webcam 路威机器人
  9. 【盘点】2017杭州云栖大会迁云实战Workshop
  10. 年轻人的第一次破产,从二次元开始
  11. Android https 自签名和CA证书验证(基于OkHttp)
  12. CIA-SSD: Confident IoU-Aware Single-Stage Object Detector From Point Cloud阅读
  13. 关于c++中vector的push_back、拷贝构造copy constructor和移动构造move constructor
  14. 编程语言的自举之路——从机器码到高级语言
  15. DCM4CHE解压缩的DICOM文件
  16. 大数据决策的五个阶段
  17. 新媒体运营教程:需求管理的避坑指南,主要需求分布在三个阶段!
  18. sqlite3.OperationalError: near “(“: syntax error
  19. 【云速建站】文件专题(上传、下载、管理)
  20. 华为鸿蒙经济新闻,华为鸿蒙生态加速 市场相关板块再度活跃

热门文章

  1. 如何量个量化策略的好坏
  2. 孙悟空的成长历程想到的
  3. 收藏!人工智能学习路径总结
  4. 使用CollectionView简单实现轮播广告栏效果
  5. 大数据定义、思维方式及架构模式
  6. 人人看得懂的ChatGPT技术原理解析
  7. 模仿探探(百合网,珍爱网)卡片左右滑动效果,滑动流畅,卡片view无限重生
  8. 亚马逊中东站好做吗?这或许是迄今为止最好的回答!
  9. 电脑问题处理篇4:解决华硕电脑“ASUS Battery Health Charging”软件界面呈现灰色不能选择充电模式的问题
  10. linux云服务器配置JDK教程(博主阿里云,腾讯云亲测成功案例教程)