• linux 内核与用户空间通信机制netlink初探


     

    1、Linux进程概述

    Linux中的进程间通信机制源自于Unix平台上的进程通信机制。Unix的两大分支AT&T Unix和BSD Unix在进程通信实现机制上各有所不同,前者形成了运行在单个计算机上的System V IPC,后者则实现了基于socket的进程间通信机制。同时Linux也遵循IEEE制定的Posix IPC标准,在三者的基础之上实现了以下几种主要的IPC机制:管道(Pipe)及命名管道(Named Pipe),信号(Signal),消息队列(Message queue),共享内存(Shared Memory),信号量(Semaphore),套接字(Socket)。通过这些IPC机制,用户空间进程之间可以完成互相通信。为了完成内核空间与用户空间通信,Linux提供了基于socket的Netlink通信机制,可以实现内核与用户空间数据的及时交换。

    2、内核与用户空间通信的方式

    到目前Linux提供了9种机制完成内核与用户空间的数据交换,分别是内核启动参数、模块参数与 sysfs、sysctl、系统调用、netlink、procfs、seq_file、debugfs和relayfs,其中模块参数与sysfs、procfs、debugfs、relayfs是基于文件系统的通信机制,用于内核空间向用户控件输出信息;sysctl、系统调用是由用户空间发起的通信机制。由此可见,以上均为单工通信机制,在内核空间与用户空间的双向互动数据交换上略显不足。Netlink是基于socket的通信机制,由于socket本身的双共性、突发性、不阻塞特点,因此能够很好的满足内核与用户空间小量数据的及时交互,因此在Linux 2.6内核中广泛使用,例如SELinux,Linux系统的防火墙分为内核态的netfilter和用户态的iptables,netfilter与iptables的数据交换就是通过Netlink机制完成。 

    3、Netlink机制及其关键技术

    3.1 Netlink机制

    Linux操作系统中当CPU处于内核状态时,可以分为有用户上下文的状态和执行硬件、软件中断两种。其中当处于有用户上下文时,由于内核态和用户态的内存映射机制不同,不可直接将本地变量传给用户态的内存区;处于硬件、软件中断时,无法直接向用户内存区传递数据,代码执行不可中断。针对传统的进程间通信机制,他们均无法直接在内核态和用户态之间使用,原因如下表:

    通信方法

    无法介于内核态与用户态的原因

    管道(不包括命名管道)

    局限于父子进程间的通信。

    消息队列

    在硬、软中断中无法无阻塞地接收数据。

    信号量

    无法介于内核态和用户态使用。

    内存共享

    需要信号量辅助,而信号量又无法使用。

    套接字

    在硬、软中断中无法无阻塞地接收数据。

    Netlink 套接字的通信依据是一个对应于进程的标识,一般定为该进程的 ID。Netlink通信最大的特点是对对中断过程的支持,它在内核空间接收用户空间数据时不再需要用户自行启动一个内核线程,而是通过另一个软中断调用用户事先指定的接收函数。通过软中断而不是自行启动内核线程保证了数据传输的及时性。

    3.2 Netlink优点

    Netlink相对于其他的通信机制具有以下优点:

    1)使用Netlink通过自定义一种新的协议并加入协议族即可通过socket API使用Netlink协议2)完成数据交换,而ioctl和proc文件系统均需要通过程序加入相应的设备或文件。

    3)Netlink使用socket缓存队列,是一种异步通信机制,而ioctl是同步通信机制,如果传输的数据量较大,会影响系统性能。

    4)Netlink支持多播,属于一个Netlink组的模块和进程都能获得该多播消息。

    5)Netlink允许内核发起会话,而ioctl和系统调用只能由用户空间进程发起。

    3.3 预定的协议

    在内核源码有关Netlink协议的头文件中包含了内核预定义的协议类型,如下所示:

    #define NETLINK_ROUTE         0  

    #define NETLINK_W1             1   

    #define NETLINK_USERSOCK     2   

    #define NETLINK_FIREWALL      3    

    #define NETLINK_INET_DIAG     4      

    #define NETLINK_NFLOG         5     

    #define NETLINK_XFRM          6      

    #define NETLINK_SELINUX       7     

    #define NETLINK_ISCSI           8     

    #define NETLINK_AUDIT          9     

    #define NETLINK_FIB_LOOKUP    10

    #define NETLINK_CONNECTOR    11

    #define NETLINK_NETFILTER      12    

    #define NETLINK_IP6_FW          13

    #define NETLINK_DNRTMSG       14    

    #define NETLINK_KOBJECT_UEVENT 15    

    #define NETLINK_GENERIC        16

    上述这些协议已经为不同的系统应用所使用,每种不同的应用都有特有的传输数据的格式,因此如果用户不使用这些协议,需要加入自己定义的协议号。对于每一个Netlink协议类型,可以有多达 32多播组,每一个多播组用一个位表示,Netlink 的多播特性使得发送消息给同一个组仅需要一次系统调用,因而对于需要多播消息的应用而言,大大地降低了系统调用的次数。

    建立Netlink会话过程如下:

     

    4、其他相关说明

    Netlink 是一种特殊的 socket,它是 Linux 所特有的,类似于 BSD 中的AF_ROUTE 但又远比它的功能强大,目前在最新的 Linux 内核(2.6.14)中使用netlink 进行应用与内核通信的应用很多,包括:路由 daemon(NETLINK_ROUTE),1-wire 子系统(NETLINK_W1),用户态 socket 协议(NETLINK_USERSOCK),防火墙(NETLINK_FIREWALL),socket 监视(NETLINK_INET_DIAG),netfilter 日志(NETLINK_NFLOG),ipsec 安全策略(NETLINK_XFRM),SELinux 事件通知(NETLINK_SELINUX),iSCSI 子系统(NETLINK_ISCSI),进程审计(NETLINK_AUDIT),转发信息表查询(NETLINK_FIB_LOOKUP),netlink connector(NETLINK_CONNECTOR),netfilter 子系统(NETLINK_NETFILTER),IPv6 防火墙(NETLINK_IP6_FW),DECnet 路由信息(NETLINK_DNRTMSG),内核事件向用户态通知(NETLINK_KOBJECT_UEVENT),通用 netlink(NETLINK_GENERIC)。

        Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 netlink。

    Netlink 相对于系统调用,ioctl 以及 /proc 文件系统而言具有以下优点:

        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则需要专门的培训才能使用

     **********对前辈们知识的一个简单总结**************

  • 相关阅读:
    UVA1292-----Strategic game-----树形DP解决树上的最小点覆盖问题
    【OpenGL游戏开发之三】OpenGl核心函数库汇总
    【Lucene】挖掘相关搜索词
    OpenMP入门教程(三)
    OpenMP入门教程(二)
    OpenMP入门教程(一)
    结构体的排序
    结构体
    循环群、对称群、陪集和拉格朗日定理、正规子群和商群
    概率论与数理统计(一)—— 随机事件与概率
  • 原文地址:https://www.cnblogs.com/potato-chip/p/9261993.html
Copyright © 2020-2023  润新知