netlink通信——用户态与内核态通信具体实现
来源:互联网 发布:有些淘宝店一万多宝贝 编辑:程序博客网 时间:2024/05/01 14:04
这篇文章主要讲解通过netlink通信机制,具体实现用户态与内核态的数据传送。我们的内核环境是2.6.35.6版本。
在</usr/include/linux/netlink.h>文件里包含了Netlink协议簇已经定义好的一些预定义协议:
#define NETLINK_ROUTE 0 /* Routing/device hook */#define NETLINK_UNUSED 1 /* Unused number */#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/* leave room for NETLINK_DM (DM Events) */#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */#define NETLINK_ECRYPTFS 19#define NETLINK_MYTEST 20
如果我们在Netlink协议簇里开发一个新的协议,只要在该文件中定义协议号即可,例如我们定义一种基于Netlink协议簇的、协议号是20的自定义协议,如上所示。同时记得,将内核头文件目录中的netlink.h也做对应的修改,在我的系统中它的路径是:/usr/src/kernels/2.6.35.6-45.fc14.i686/include/linux/netlink.h
接下来我们在用户空间以及内核空间模块的开发过程中就可以使用这种协议了,需要说明的是,如果在这两个文件中不添加协议号,就需要在具体通信实现代码文件中添加这两个协议号,在我的具体实现中,就是采用这种方法。
用户态通信代码(mynlusr.c):
#include <stdio.h>#include <stdlib.h>#include <sys/stat.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <linux/netlink.h>#include <linux/socket.h>#define NETLINK_MYTEST 20#define MAX_PAYLOAD 1024int main(int argc, char ** argv){struct sockaddr_nl src_addr,dest_addr;struct nlmsghdr *nlh = NULL;struct msghdr msg;struct iovec iov;int sock_fd = -1;/*创建套接字*/if(-1 == (sock_fd = socket(AF_NETLINK,SOCK_RAW,NETLINK_MYTEST))){printf("can't create netlink socket!\n");return -1;}/*设置src_addr结构*/memset(&src_addr, 0, sizeof(src_addr));src_addr.nl_family = AF_NETLINK;src_addr.nl_pid = getpid();/*自己的pid*/src_addr.nl_groups = 0;/*将套接字和netlink地址结构进行绑定*/if(-1 == bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr))){printf("can't bind sock_fd with sockaddr_nl");return -1;}if(NULL == (nlh=(struct nlmsghdr*)malloc(NLMSG_SPACE(MAX_PAYLOAD)))){printf("alloc mem failed!\n");return -1;}memset(nlh, 0, MAX_PAYLOAD);/*填充netlink的消息头部*/nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);nlh->nlmsg_pid = getpid();nlh->nlmsg_type = NLMSG_NOOP;nlh->nlmsg_flags = 0;/*设置netlink的消息内容*/strcpy(NLMSG_DATA(nlh), argv[1]);memset(&iov, 0, sizeof(iov));iov.iov_base = (void *)nlh;iov.iov_len = nlh->nlmsg_len;/*设置dest_addr结构*/memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.nl_family = AF_NETLINK;dest_addr.nl_pid = 0;/*目的地址的pid,这里是发送给内核*/dest_addr.nl_groups = 0;memset(&msg, 0, sizeof(msg));msg.msg_name = (void *)&dest_addr;msg.msg_namelen = sizeof(dest_addr);msg.msg_iov = &iov;msg.msg_iovlen = 1;/*通过netlink socket向内涵发送消息*/sendmsg(sock_fd, &msg, 0);/*接受内核消息*/printf("waiting message from kernel!\n");memset((char *)NLMSG_DATA(nlh),0,1024);recvmsg(sock_fd,&msg,0);printf("response:%s\n",NLMSG_DATA(nlh));/*关闭netlink套接字*/close(sock_fd);free(nlh);return 0;}
内核态通信代码(mynlkern.c):
#include <linux/kernel.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/skbuff.h>#include <linux/init.h>#include <linux/ip.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/netlink.h>#include <net/sock.h>#include <net/netlink.h>#define NETLINK_MYTEST 20#define MAX_MSGSIZE 1024struct sock *nl_sk = NULL;static void sendnlmsg(char *message, int dstpid){struct sk_buff *skb;struct nlmsghdr *nlh;int len = NLMSG_SPACE(MAX_MSGSIZE);int slen = 0;if(!message || !nl_sk){return ;}/*为新的sk_buffer申请空间*/skb = alloc_skb(len,GFP_KERNEL);if(!skb){printk(KERN_ERR "my_net_link:alloc_skb Error!\n");return ;}slen = strlen(message);/*用nlmsg_put来设置netlink消息头部*/nlh = nlmsg_put(skb,0,0,0,MAX_MSGSIZE,0);/*设置Netlink的控制块*/NETLINK_CB(skb).pid = 0;/*消息发送者的id标识,如果是内核发的则置0*/NETLINK_CB(skb).dst_group = 0;/*如果目的的组为内核或某一进程,该字段为0*/message[slen] = '\0';memcpy(NLMSG_DATA(nlh),message,slen+1);/*通过netlink_unicast将消息发送给用户空间*/printk("kernel:begin send\n");netlink_unicast(nl_sk,skb,dstpid,0);printk("kernel:send OK!\n");return ;}static void nl_data_ready(struct sk_buff* skb){struct nlmsghdr *nlh;u64 rlen;void *data;while(skb->len >= NLMSG_SPACE(0)){nlh = nlmsg_hdr(skb);printk("nlh->nlmsg_pid=%u skb->len =%d NLMSG_SPACE(0)=%d\n",nlh->nlmsg_pid,skb->len,NLMSG_SPACE(0));if(nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len)return ;rlen = NLMSG_ALIGN(nlh->nlmsg_len);if(rlen > skb->len)rlen = skb->len;data = NLMSG_DATA(nlh);printk("received netlink message: %s\n",(char *)data);skb_pull(skb, rlen);sendnlmsg("send from kernel",nlh->nlmsg_pid);}printk("received finished!\n");}static int __init myinit_module(void){printk("my netlink in!\n");nl_sk = netlink_kernel_create(&init_net, NETLINK_MYTEST, 0, nl_data_ready, NULL, THIS_MODULE);if(!nl_sk){ printk(KERN_ERR "my_net_link: create netlink socket error!\n"); return 1; }else{return 0;}}static void __exit myexit_module(void){printk("my netlink out!\n");if(nl_sk != NULL){sock_release(nl_sk->sk_socket);}}MODULE_AUTHOR("Fang Xieyun");MODULE_LICENSE("GPL");module_init(myinit_module);module_exit(myexit_module);
- netlink通信——用户态与内核态通信具体实现
- Linux内核态与用户态通信篇(一)—— Netlink
- linux用户态与内核态通信netlink
- Netlink实现Linux内核与用户空间通信
- Netlink实现Linux内核与用户空间通信
- Netlink实现Linux内核与用户空间通信
- Netlink实现Linux内核与用户空间通信
- 用户空间与内核通信-netlink
- 内核态下netlink和用户态程序通信
- netlink socket 用户态和内核态的通信
- linux用户态和内核态通信之netlink机制
- linux用户态和内核态通信之netlink机制
- linux 用户态和内核通信之Netlink
- linux内核与用户之间的通信方式——虚拟文件系统、ioctl以及netlink
- linux内核与用户之间的通信方式——虚拟文件系统、ioctl以及netlink .
- 《Linux 系统内核空间与用户空间通信的实现与分析》 Netlink 机制实现
- netlink socket实现内核和用户的通信
- linux 内核与用户空间通信之netlink使用方法[转]
- 模拟新浪微博登陆
- 《大唐豪侠》架构开发纪实
- linux 共享内存
- (iPhone/iPad开发)iOS中生成随机数
- WPF中listview数据绑定
- netlink通信——用户态与内核态通信具体实现
- 【实习笔试面试题】2013网易互联网实习笔试算法题-找出最大连续自然数个数
- GridView的RowDataBound事件写法
- vs2010最全快捷键
- Java NIO学习(一)
- 解决HTML SELECT控件 disabled 后无法向后台传值的方法
- linux 下连接mysql服务器
- 大型网站框架的演变
- AndEngine绘制滚动文本TickerText