NetLink使用实例(YGM)

上传人:206****923 文档编号:51271309 上传时间:2018-08-13 格式:DOC 页数:6 大小:77KB
返回 下载 相关 举报
NetLink使用实例(YGM)_第1页
第1页 / 共6页
NetLink使用实例(YGM)_第2页
第2页 / 共6页
NetLink使用实例(YGM)_第3页
第3页 / 共6页
NetLink使用实例(YGM)_第4页
第4页 / 共6页
NetLink使用实例(YGM)_第5页
第5页 / 共6页
点击查看更多>>
资源描述

《NetLink使用实例(YGM)》由会员分享,可在线阅读,更多相关《NetLink使用实例(YGM)(6页珍藏版)》请在金锄头文库上搜索。

1、如何使用如何使用 NetlinkNetlink ConnectorConnectorAuthor: Yang gongming简介:简介: 本文详细介绍了 Linux 2.6.34.14 内核引入的内核空间与用户空间通 信的新机制连接器,并通过典型示例讲解了它的使用。一、一、概述概述连接器是一种新的用户态与内核态的通信方式,它使用起来非常方便。本质上, 连接器是一种 netlink,它的 netlink 协议号为 NETLINK_CONNECTOR,与一般 的 netlink 相比,它提供了更容易的使用接口,使用起来更方便。netlink 本 质上是 socket,不过它可用于用户程序和内核程

2、序的通信。1.1.内核模块使用方法内核模块使用方法注册一个标识 ID 和回调函数,即可使用连接器。cn_msg 结构:/标识 netlink 的 IDstruct cb_id _u32idx; _u32val; ; /netlink 控制信息头 struct cn_msg struct cb_id id; _u32seq; _u32ack; _u32len;/* Length of the following data */ _u8data0; ; 三个内核模块常用的 API。 int cn_add_callback(struct cb_id *id, char *name, void (*c

3、allback) (void *);void cn_del_callback(struct cb_id *id); void cn_netlink_send(struct cn_msg *msg, u32 _group, int gfp_mask);结构 cb_id 是连接器实例的标识 ID,它用于确定 netlink 消息与回调函数的 对应关系。当连接器接收到标识 ID 为 idx,val 的 netlink 消息时,注册 的回调函数 void (*callback) (void *) 将被调用。该回调函数的参数为结构 struct cn_msg 的指针。接口函数 cn_add_callba

4、ck 用于向连接器注册新的连接器实例以及相应的回调 函数,参数 id 指定注册的标识 ID,参数 name 指定连接器回调函数的符号名, 参数 callback 为回调函数。接口函数 cn_del_callback 用于卸载回调函数,参数 id 为注册函数 cn_add_callback 注册的连接器标识 ID。接口函数 cn_netlink_send 用于向给定的组发送消息,它可以在任何上下文安 全地调用。但是,如果内存不足,可能会发送失败。在具体的连接器实例中, 该函数用于向用户态发送 netlink 消息。参数 msg 为发送的 netlink 消息的消息头。参数 _group 为接收消

5、息的组。 用户侧接收消息,不需要注册 idx 和 val,所以,内核调用 cn_add_callback 时的 idx 和 val 对将数据报文发送到那个用户没有任何影响。如果它为 0,那 么连接器将搜索所有注册的连接器用户,也不会发送给用户 ID 与在 msg 中的 ID 相同的组。在_group=0 时,甚至不会发送给0 的用户组。但如果 _group 不为 0,消息将发送给 _group 指定的组。参数 gfp_mask 指定页分 配标志。用户接收方,通过:socket()函数和 bind 函数,以及 setsockopt()函数,设 置接收组。只通过组来接收。当 bind 函数中 so

6、ckaddr_nl 中的 group 设置为 0xffff 或大于该值,将接收到所有的组的消息,也不管是否在 setsockopt()函 数中设置的组参数是多少。对于非 0xffff 参数,bind 的 sockaddr_nl 的 goup 必须和 setsockopt()的组保持一致。这样才能收到内核发送到指定组(_group)的 消息。cn_msg 是连接器定义的消息头,字段 seq 和 ack 用于确保消息的可靠传输, 刚才已经提到,netlink 在内存紧张的情况下可能丢失消息,因此该头使用顺 序号和响应号来满足要求可靠传输用户的需求。当发送消息时,用户需要设置 独一无二的顺序号和随机

7、的响应号,顺序号也应当设置到 nlmsghdr- nlmsg_seq。注意 nlmsghdr 是类型为结构 struct nlmsghdr 的变量,它用于 设置或保存 netlink 的消息头。每发送一个消息,顺序号应当加 1,如果需要 发送响应消息,那么响应消息的顺序号应当与被响应的消息的顺序号相同,同 时响应消息的响应号应当为被响应消息的顺序号加 1。如果接收到的消息的顺 序号不是期望的顺序号,那表明该消息是一个新的消息,如果接收到的消息的 顺序号是期望的顺序号,但它的响应号不等于上次发送消息的顺序号加 1,那 么它也是新消息。用户层接收到消息后,对序号以及 idx 和 val 的处理,需

8、要接收后进行比较, 以判断丢弃或其他处理。2.2.用户态使用用户态使用方法方法用户层绑定一个接收用户组。 int group = 5; s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); l_local.nl_family = AF_NETLINK; l_local.nl_groups = group; l_local.nl_pid = getpid(); if (bind(s, (struct sockaddr *) close(s); return -1; setsockopt(s, SOL_NETLINK, NETLINK_ADD

9、_MEMBERSHIP, 在不需要使用该连接器时使用语句setsockopt(s, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, -如上红色部分是非常重要的参数。二、下面从几个维度来分析二、下面从几个维度来分析 netlinknetlink connectconnect 的使用方法的使用方法1.1.内核发送:内核发送: /首先注册回调函数。不管是收还是发,都必须注册。 cn_add_callback( cn_test_id: idx 和 Val 是接收数据的参数。cn_test_callback 是接收的回调 函数。这几个参数和发送无关。 /buffer 结构为:

10、 cn_msg 结构体+纯数据。 纯数据长度由 m-len 指定。 cn_msg * m = kzalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);m-id.idx = 11;/anym-id.val =234;/any m-seq =0;/any m-len = sizeof(“Hi 美女?“);/必须为附加数据的长度memcpy(m + 1,“Hi 美女?“, m-len);/发送到指定的组group=13; cn_netlink_send(m,group, GFP_ATOMIC);如上程序,即完成 netlink 的发送。一定要关注好 group

11、的含义,否则无法被 用户层接收到报文。2.2.用户层接收:用户层接收: /netlink 是 socket,所以必须 socket 一下。红色字体必须正确使用。 /如果没有定义 NETLINK_CONNECTOR ,可直接用 11 来指定是 connector memset(buf, 0, sizeof(buf); s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); /将 socket 和 netlink 绑定。 l_local.nl_family = AF_NETLINK; l_local.nl_groups = 0; l_local

12、.nl_pid = 3;/anybind(s, (struct sockaddr *)setsockopt(s,270,1, 如上代码: nl_groups 在 linux 文档中描述为掩码,具体如何算法不清楚,也 没有精力去分析。如果要广播,就设置 nl_groups=0xffffffff 即可。否则,就 设置改组和 group 一样。这样只有发送到 group 的消息才会被接收。对于内核 到用户层要实现组播,个人觉得没有必要。从实验结果来看,2.6.34.14 内核 还有待完善。 如上代码完成后,就可接收报文了。memset(buf, 0, sizeof(buf); len = recv(

13、s, buf, sizeof(buf), 0); reply = (struct nlmsghdr *)buf; data = (struct cn_msg *)(reply+1);接收代码很简单,数据的结构为: nlmsghdr+cn_msg+data len 的长度 = nlmsghdr+cn_msg+data+addlen(四字节对齐所长出来的长度。如 果恰巧是 4 的整数倍,addlen=0); reply-nlmsg_len =len; data-len =data(发送的数据包)的长度。2.2.用户层发送用户层发送 用户层发送是个体力活,方法如下:sd = socket(PF_NE

14、TLINK,SOCK_RAW,NETLINK_CONNECTOR);saddr.nl_family = AF_NETLINK;saddr.nl_pid = 0; /任意saddr.nl_groups = -1;/-10xfffff,表示都接收。bind(sd,(struct sockaddr*)int x=8;setsockopt(sd,270,1, /开始发送;当然,先要申请 buffer1024,足够大。/size 为带字节对齐的总长度,最好用 NLMSG_SPACE。size = NLMSG_SPACE(sizeof(struct cn_msg) + 68); nlh=(struct n

15、lmsghdr *)buffer;nlh-nlmsg_seq = sid+;/自定义nlh-nlmsg_pid = getpid();/自定义nlh-nlmsg_type = 3;/固定为 3nlh-nlmsg_len = NLMSG_LENGTH(size-sizeof(*nlh);/总长度。nlh-nlmsg_flags = 0;data = NLMSG_DATA(nlh);/找到存放 cn_msg 的地方data-id.idx =0x11;/内核程序在 cn_add_callback 时的参数。data-id.val =0x33;/内核程序在 cn_add_callback 时的参数。d

16、ata-seq = sid+;/可以自定义data-ack =0;/可以自定义data-len = 68;/要发送数据的长度len =send(sd,nlh,size,0);sd 为 socket 的 id,nlh 为 buffer 起始位置,size 为总长度,0(都选择 0)。3.3.内核层接收内核层接收 re_v = cn_add_callback( void * my_callback(struct cn_msg* msg,struct netlink_skb_parms* parms) /接收函数处理。 如上所示,首先 cn_add_callback 一下。 然后,my_callback 将不断接收来自用户层的消息。 struct netlink_skb_parms struct ucredcreds;/* Skb credentials*/ _u32pid; _u32

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 商业/管理/HR > 其它文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号