linux 内核与用户空间通信之netlink使用方法.doc
《linux 内核与用户空间通信之netlink使用方法.doc》由会员分享,可在线阅读,更多相关《linux 内核与用户空间通信之netlink使用方法.doc(11页珍藏版)》请在三一文库上搜索。
1、linux 内核与用户空间通信之netlink使用方法1引言Linux中的进程间通信机制源自于Unix平台上的进程通信机制。Unix的两大分支AT其中net参数是网络设备命名空间指针,input函数是netlink socket在接受到消息时调用的回调函数指针,module默认为THIS_MODULE.然后用户空间进程使用标准Socket API来创建套接字,将进程ID发送至内核空间,用户空间创建使用socket()创建套接字,该函数的原型如下:int socket(int domain, int type, int protocol);其中domain值为PF_NETLINK,即Netlin
2、k使用协议族。protocol为Netlink提供的协议或者是用户自定义的协议,Netlink提供的协议包括NETLINK_ROUTE, NETLINK_FIREWALL, NETLINK_ARPD, NETLINK_ROUTE6和 NETLINK_IP6_FW。接着使用bind函数绑定。Netlink的bind()函数把一个本地socket地址(源socket地址)与一个打开的socket进行关联。完成绑定,内核空间接收到用户进程ID之后便可以进行通讯。用户空间进程发送数据使用标准socket API中sendmsg()函数完成,使用时需添加struct msghdr消息和nlmsghdr消
3、息头。一个netlink消息体由nlmsghdr和消息的payload部分组成,输入消息后,内核会进入nlmsghdr指向的缓冲区。内核空间发送数据使用独立创建的sk_buff缓冲区,Linux定义了如下宏方便对于缓冲区地址的设置,如下所示:#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)参数sk为函数netlink_kernel_create()返回的socket,参数skb存放消息,它的data字段指向要发送的netlink消息结构,而skb的控制块保存了消息的地址信息,前面的宏NETLINK_CB(skb)就用于方便设置该控制块,
4、参数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为接收消息的多播组,该参数的每一个代表一个多播组,因此如果发送给多个多播组,就把该参数
5、设置为多个多播组组ID的位或。参数allocaTIon为内核内存分配类型,一般地为GFP_ATOMIC或GFP_KERNEL,GFP_ATOMIC用于原子的上下文(即不可以睡眠),而GFP_KERNEL用于非原子上下文。接收数据时程序需要申请足够大的空间来存储netlink消息头和消息的payload部分。然后使用标准函数接口recvmsg()来接收netlink消息4 Netlink通信过程调试平台:Vmware 5.5 + Fedora Core 10(两台,一台作为host机,一台作为target机)。调试程序:分为内核模块和用户空间程序两部分,当内核模块被加载后,运行用户空间程序,由用
6、户空间发起Netlink会话,和内核模块进行数据交换。被加载的内核模块无法通过外加的调试器进行调试,KGDB提供了一种内核源码级别的调试机制。Linux内核自2.6.26版本之后在内核中内置了KGDB选项,编译内核时需要选择与之相关的选项,调试时host端需使用带有符号表的vmlinz内核,target端使用gdb调试用户空间的程序。用户空间程序关键代码如下:int send_pck_to_kern(u8 op, const u8 *data, u16 data_len) struct user_data_ *pck; int ret; pck = (struct user_data_*)ca
7、lloc(1, sizeof(*pck) + data_len); if(!pck) printf(calloc in %s failed!n, _FUNCTION_); return -1; pck-magic_num = MAGIC_NUM_RNQ; pck-op = op; pck-data_len = data_len; memcpy(pck-data, data, data_len); ret = send_to_kern(const u8*)pck, sizeof(*pck) + data_len); if(ret) printf(send_to_kern in %s failed
8、!n, _FUNCTION_); free(pck); return ret ? -1 : 0; static void recv_from_nl() char buf1000; int len; struct iovec iov = buf, sizeof(buf); struct sockaddr_nl sa; struct msghdr msg; struct nlmsghdr *nh; memset( msg.msg_name = (void *) msg.msg_namelen = sizeof(sa); msg.msg_iov = msg.msg_iovlen = 1; /len
9、= recvmsg(nl_sock, len = recvmsg(nl_sock, for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT (nh, len) / The end of multipart message. if (nh-nlmsg_type = NLMSG_DONE) puts(nh-nlmsg_type = NLMSG_DONE); return; if (nh-nlmsg_type = NLMSG_ERROR) / Do some error handling. puts(nh-nlmsg_
10、type = NLMSG_ERROR); return; #if 1 puts(Data received from kernel:); hex_dump(u8*)NLMSG_DATA(nh), NLMSG_PAYLOAD(nh, 0);#endif 内核模块需要防止资源抢占,保证Netlink资源互斥占有,内核模块部分关键代码如下:staTIc void nl_rcv(struct sk_buff *skb) mutex_lock( netlink_rcv_skb(skb, mutex_unlock( staTIc int nl_send_msg(const u8 *data, int da
11、ta_len) struct nlmsghdr *rep; u8 *res; struct sk_buff *skb; if(g_pid 0) printk(Data to be send to user space:n); hex_dump(void*)data, data_len); rep = _nlmsg_put(skb, g_pid, 0, NLMSG_NOOP, data_len, 0); res = nlmsg_data(rep); memcpy(res, data, data_len); netlink_unicast(g_nl_sk, skb, g_pid, MSG_DONT
12、WAIT); return 0; staTIc int nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) const u8 res_data = Hello, user; size_t data_len; u8 *buf; struct user_data_ *pck; struct user_req *req, *match = NULL; g_pid = NETLINK_CB(skb).pid; buf = (u8*)NLMSG_DATA(nlh); data_len = nlmsg_len(nlh); if(data_len ma
13、gic_num != MAGIC_NUM_RNQ) printk(Magic number not matched!n); return -1; if(g_debug_level 0) printk(Data from user space:n); hex_dump(buf, data_len); req = user_reqs; while(req-op) if(req-op = pck-op) match = req; break; req+; if(match) match-handler(buf, data_len); nl_send_msg(res_data, sizeof(res_
14、data); return 0;5.其他相关说明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)
15、,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(N
16、ETLINK_GENERIC)。Netlink 是一种在内核与用户应用间进行双向数据传输的非常好的方式,用户态应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,内核态需要使用专门的内核 API 来使用 netlink。Netlink 相对于系统调用,ioctl 以及 /proc 文件系统而言具有以下优点:1,为了使用 netlink,用户仅需要在 include/linux/netlink.h 中增加一个新类型的 netlink 协议定义即可, 如 #define NETLINK_MYTEST 17 然后,内核和用户态应用就可以立即通过 socket API 使
17、用该 netlink 协议类型进行数据交换。但系统调用需要增加新的系统调用,ioctl 则需要增加设备或文件, 那需要不少代码,proc 文件系统则需要在 /proc 下添加新的文件或目录,那将使本来就混乱的 /proc 更加混乱。2. netlink是一种异步通信机制,在内核与用户态应用之间传递的消息保存在socket缓存队列中,发送消息只是把消息保存在接收者的socket的接收队列,而不需要等待接收者收到消息,但系统调用与 ioctl 则是同步通信机制,如果传递的数据太长,将影响调度粒度。3使用 netlink 的内核部分可以采用模块的方式实现,使用 netlink 的应用部分和内核部分没
18、有编译时依赖,但系统调用就有依赖,而且新的系统调用的实现必须静态地连接到内核中,它无法在模块中实现,使用新系统调用的应用在编译时需要依赖内核。4netlink 支持多播,内核模块或应用可以把消息多播给一个netlink组,属于该neilink 组的任何内核模块或应用都能接收到该消息,内核事件向用户态的通知机制就使用了这一特性,任何对内核事件感兴趣的应用都能收到该子系统发送的内核事件,在后面的文章中将介绍这一机制的使用。5内核可以使用 netlink 首先发起会话,但系统调用和 ioctl 只能由用户应用发起调用。6netlink 使用标准的 socket API,因此很容易使用,但系统调用和
19、ioctl则需要专门的培训才能使用。用户态使用 netlink用户态应用使用标准的socket APIs, socket(), bind(), sendmsg(), recvmsg() 和 close() 就能很容易地使用 netlink socket,查询手册页可以了解这些函数的使用细节,本文只是讲解使用 netlink 的用户应该如何使用这些函数。注意,使用 netlink 的应用必须包含头文件 linux/netlink.h。当然 socket 需要的头文件也必不可少,sys/socket.h。为了创建一个 netlink socket,用户需要使用如下参数调用 socket():soc
20、ket(AF_NETLINK, SOCK_RAW, netlink_type)第一个参数必须是 AF_NETLINK 或 PF_NETLINK,在 Linux 中,它们俩实际为一个东西,它表示要使用netlink,第二个参数必须是SOCK_RAW或SOCK_DGRAM,第三个参数指定netlink协议类型,如前面讲的用户自定义协议类型NETLINK_MYTEST, NETLINK_GENERIC是一个通用的协议类型,它是专门为用户使用的,因此,用户可以直接使用它,而不必再添加新的协议类型。内核预定义的协议类型有:#define NETLINK_ROUTE 0#define NETLINK_W1
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 内核与用户空间通信之netlink使用方法 内核 用户 空间 通信 netlink 使用方法
链接地址:https://www.31doc.com/p-3255206.html