日期:2014-05-16  浏览次数:20608 次

linux学习笔记:netlink实践演练

内核和用户空间之间存在如下交互手段:

1.内核启动参数 2.模块参数与 3.sysfs、4.sysctl、5.系统调用、6.netlink、7.procfs、8.seq_file、9.debugfs 10.relayfs

另外 call_usermodehelper 可以从内核发起用户态的应用程序运行

  其中netlink作为一种进程之间的通讯手段 ,和其他内核与用户空间的通讯手段比较,有很大的优势:

 1.  新增通讯通道的灵活性:

     netlink提供了一套完善的机制,用户既可以静态的增加通讯通道,也可以动态的创建通讯通道,这样用户可以很灵活的根据自己的需要来定制和开发。

  2. 丰富的特性支持:

     netlink可以支持异步双工, 其他机制只支持用户到内核单向的通道,或者只支持内核到用户的单向通道,netlink支持对称的双向通道。

      同时neilink支持单点传输和多点传输,这些优势都是其他通讯机制所不具备的。

 3. 传输效率比较高:  

     和其他用户向内核通讯手段一样,netlink也是借助某些系统调用接口实现的,并且netlink的目标数据接收操作是直接在软中断里面执行的,比有些在内核开辟线程接收数据的方式要快。

 4. 易于扩展:

     内核已为netlink提供的动态机制扩展,新增一个应用通道非常方便,只需要修改少量代码。

      netlink充分体现了linux开发的宗旨:“提供机制而不是策略”,“do one thing and do it well”, 从内核版本的演进历程看来,同一类型的机制,linux提供的功能越来越强大,给用户的选择空间也是越来越丰富。

从学习的角度出发,这里使用静态方式新增了一个netlink通道,并实现了一个用户态和内核态通讯的双向通讯的样例,设计如下:

       user                                                    kernel

          |                                                                |

        send    -> "hello from usr"->  receive and print 

           |                                                               |

 receive and print  < -"hello from usr " <-send

           |                                                               |

         exit

 如上图所述,由用户首先发起一个问候消息给内核,内核收到这个消息以后返回一个问候消息给用户, 以下通过代码来分析netlink的实现:

一、内核部分代码:

1. 头文件和静态申明

这里包含了必要的头文件, 新增了一个 netlink协议号,这个协议号和内核自定义的NETLINK_GENERIC是同一类型,应该定义在<linux/netlink.h>中,为了方便显示放到了这里。

新增内核源码文件 eknetlink.c :

/*kernel example code of netlink*/
#include <linux/netlink.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/spinlock.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include <net/flow.h>

#define NETLINK_EXAMPLE		31  /*新增netlink协议号*/

/*本netlink过滤类型*/
enum nf_eknetlink_hooks {
    NF_EKNETLINK_IN,                 
    NF_EKNETLINK_OUT