打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Netlink—基于socket的Linux内核—用户空间通信机制(2)
Netlink—基于socket的Linux内核—用户空间通信机制(2)
2009-10-27 16:00

3.3 Netlink关键技术

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

#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 的多播特性使得发送消息给同一个组仅需要一次系统调用,因而对于需要多拨消息的应用而言,大大地降低了系统调用的次数。

建立Netlink会话过程如下:


内核使用与标准socket API类似的一套API完成通信过程。首先通过netlink_kernel_create()创建套接字,该函数的原型如下:

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);

其中net参数是网络设备命名空间指针,input函数是netlink socket在接受到消息时调用的回调函数指针,module默认为THIS_MODULE.

然后用户空间进程使用标准Socket API来创建套接字,将进程ID发送至内核空间,用户空间创建使用socket()创建套接字,该函数的原型如下:

int socket(int domain, int type, int protocol);

其中domain值为PF_NETLINK,即Netlink使用协议族。protocolNetlink提供的协议或者是用户自定义的协议,Netlink提供的协议包括NETLINK_ROUTE, NETLINK_FIREWALL, NETLINK_ARPD, NETLINK_ROUTE6 NETLINK_IP6_FW

接着使用bind函数绑定。Netlinkbind()函数把一个本地socket地址(socket地址)与一个打开的socket进行关联。完成绑定,内核空间接收到用户进程ID之后便可以进行通讯。

用户空间进程发送数据使用标准socket APIsendmsg()函数完成,使用时需添加struct msghdr消息和nlmsghdr消息头。一个netlink消息体由nlmsghdr和消息的payload部分组成,输入消息后,内核会进入nlmsghdr指向的缓冲区。

内核空间发送数据使用独立创建的sk_buff缓冲区,Linux定义了如下宏方便对于缓冲区地址的设置,如下所示:

#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))

在对缓冲区设置完成消息地址之后,可以使用netlink_unicast()来发布单播消息,netlink_unicast()原型如下:

int netlink_unicast(struct sock *sk, struct sk_buff *skb, u32 pid, int nonblock);

参数sk为函数netlink_kernel_create()返回的socket,参数skb存放消息,它的data字段指向要发送的netlink消息结构,而skb的控制块保存了消息的地址信息,前面的宏NETLINK_CB(skb)就用于方便设置该控制块, 参数pid为接收消息进程的pid,参数nonblock表示该函数是否为非阻塞,如果为1,该函数将在没有接收缓存可利用时立即返回,而如果为0,该函数在没有接收缓存可利用时睡眠。

内核模块或子系统也可以使用函数netlink_broadcast来发送广播消息:

void netlink_broadcast(struct sock *sk, struct sk_buff *skb, u32 pid, u32 group, int allocation);

前面的三个参数与netlink_unicast相同,参数group为接收消息的多播组,该参数的每一个代表一个多播组,因此如果发送给多个多播组,就把该参数设置为多个多播组组ID的位或。参数allocation为内核内存分配类型,一般地为GFP_ATOMICGFP_KERNELGFP_ATOMIC用于原子的上下文(即不可以睡眠),而GFP_KERNEL用于非原子上下文。

接收数据时程序需要申请足够大的空间来存储netlink消息头和消息的payload部分。然后使用标准函数接口recvmsg()来接收netlink消息。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
linux 内核和用户空间通信之netlink使用方法
用户空间和内核空间通讯之Netlink
用户空间和内核空间通讯之【Netlink 下】
linux netlink通信机制
netlink socket 编程之 why & how - 内核源码 - ChinaUn...
2.6.24以上内核中netlink使用方法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服