linux 用户态和内核通信之Netlink
来源:互联网 发布:供应链管理软件 java 编辑:程序博客网 时间:2024/05/21 12:42
http://www.linuxidc.com/Linux/2011-07/39085p2.htm
之前参考这篇帖子练习了一下netlink,当时记得可以正常调试成功,今天在自己笔记本上ubuntu 12.04 上调试了一下,结果一直出现kernel panic, 调试了一下发现应该是出现在kernel 向用户空间发送消息的流程中。至今没调试成功,记录一下吧,抽时间在调试一下:
用户空间:
/* * netlink_user.c */#include <sys/stat.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/types.h>#include <string.h>#include <asm/types.h>#include <linux/netlink.h>#include <linux/socket.h>#include <errno.h>#define NETLINK_TEST 25#define MAX_PAYLOAD 1024 // maximum payload sizeint main(int argc, char* argv[]){ int state; struct sockaddr_nl src_addr, dest_addr; struct nlmsghdr *nlh = NULL; struct iovec iov; struct msghdr msg; int sock_fd, retval; int state_smg = 0; // Create a socket sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST); if(sock_fd == -1){ printf("error getting socket: %s", strerror(errno)); return -1; } // To prepare binding memset(&msg,0,sizeof(msg)); memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); // self pid src_addr.nl_groups = 0; // multi cast retval = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)); if(retval < 0){ printf("bind failed: %s", strerror(errno)); close(sock_fd); return -1; } // To prepare recvmsg nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD)); if(!nlh){ printf("malloc nlmsghdr error!\n"); close(sock_fd); return -1; } memset(&dest_addr,0,sizeof(dest_addr)); dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0; dest_addr.nl_groups = 0; nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = 0; strcpy(NLMSG_DATA(nlh),"Hello you!"); iov.iov_base = (void *)nlh; iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD); // iov.iov_len = nlh->nlmsg_len; 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; printf("state_smg\n"); state_smg = sendmsg(sock_fd,&msg,0); if(state_smg == -1) { printf("get error sendmsg = %s\n",strerror(errno)); } memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD)); printf("waiting received!\n"); // Read message from kernel while(1){ printf("In while recvmsg\n"); state = recvmsg(sock_fd, &msg, 0); if(state<0) { printf("state<1"); } printf("In while\n"); printf("Received message: %s\n",(char *) NLMSG_DATA(nlh)); } close(sock_fd); return 0;}内核空间:
/* * netlink_kernel.c */#include <linux/init.h>#include <linux/module.h>#include <linux/timer.h>#include <linux/time.h>#include <linux/types.h>#include <net/sock.h>#include <net/netlink.h>#define NETLINK_TEST 25#define MAX_MSGSIZE 1024int stringlength(char *s);void sendnlmsg(char* message);int pid;int err;struct sock *nl_sk = NULL;int flag = 0;void sendnlmsg(char* message){ struct sk_buff *skb_1; struct nlmsghdr *nlh; int len = NLMSG_SPACE(MAX_MSGSIZE); int slen = 0; if(!message || !nl_sk) { return ; } skb_1 = alloc_skb(len,GFP_KERNEL); if(!skb_1) { printk(KERN_ERR "my_net_link:alloc_skb_1 error\n"); } slen = stringlength(message); nlh = nlmsg_put(skb_1,0,0,0,MAX_MSGSIZE,0); NETLINK_CB(skb_1).pid = 0; NETLINK_CB(skb_1).dst_group = 0;message[slen]= '\0';memcpy(NLMSG_DATA(nlh),message,slen+1);printk("my_net_link:send message '%s'.\n",(char *)NLMSG_DATA(nlh)); netlink_unicast(nl_sk,skb_1,pid,MSG_DONTWAIT);}int stringlength(char *s){ int slen = 0; for(; *s; s++){ slen++; } return slen;}void nl_data_ready(struct sk_buff *__skb) {struct sk_buff *skb;struct nlmsghdr *nlh;char str[100];struct completion cmpl;int i=10;printk(KERN_ALERT "entering nl_data_ready\n");skb = skb_get (__skb);if(skb->len >= NLMSG_SPACE(0)){nlh = nlmsg_hdr(skb);memcpy(str, NLMSG_DATA(nlh), sizeof(str));printk("Message received:%s\n",str) ;pid = nlh->nlmsg_pid;printk(KERN_ALERT "pid is: %d\n",pid);/*while(i--){init_completion(&cmpl);wait_for_completion_timeout(&cmpl,3 * HZ);sendnlmsg("I am from kernel!");}*///NETLINK_CB(skb).groups = 0; /* not in mcast group */NETLINK_CB(skb).pid = 0; /* from kernel *///NETLINK_CB(skb).dst_pid = pid;NETLINK_CB(skb).dst_group = 0; /* unicast */ //netlink_unicast(nl_sk,skb,pid,MSG_DONTWAIT);flag = 1;kfree_skb(skb); } }// Initialize netlinkint netlink_init(void){ nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, 1, nl_data_ready, NULL, THIS_MODULE); if(!nl_sk){ printk(KERN_ERR "my_net_link: create netlink socket error.\n"); return 1; } printk("my_net_link_3: create netlink socket ok.\n"); return 0;}static void netlink_exit(void){ if(nl_sk != NULL){ sock_release(nl_sk->sk_socket); } printk("my_net_link: self module exited\n");}module_init(netlink_init);module_exit(netlink_exit);MODULE_AUTHOR("xxxxxxx");MODULE_LICENSE("GPL");Makefile:
obj-m := netlink_kernel.oKERNELBUILD := /lib/modules/`uname -r`/builddefault:@echo "BUILE Kmod"@make -C $(KERNELBUILD) M=$(shell pwd)gcc -o netlink_user netlink_user.cclean:@echo " CLEAN kmod"@rm -rf *.o@rm -rf .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers .*.d
- linux用户态和内核态通信之netlink机制
- linux用户态和内核态通信之netlink机制
- linux 用户态和内核通信之Netlink
- linux 内核和用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法[转]
- linux 内核与用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法
- Linux内核空间与用户空间通信之netlink
- linux 内核与用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法
- Linux 内核与用户空间通信之 netlink 使用方法
- linux 内核与用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法
- linux 内核与用户空间通信之netlink使用方法
- 单点登录
- 简单返回顶部代码及注释说明
- 在C#中使用System.Timers.Timer
- iOS越狱之程序获得root权限
- JSP语法
- linux 用户态和内核通信之Netlink
- 黑马程序员java笔记之九-----交通灯信号管理系统
- C#发现之旅全系列
- python debug 工具pdb
- c++内存中的对象布局分析
- 科学与艺术
- 我指间的刺青是对你的誓言
- Proper Screencasting on Linux
- ssh hibernate struts spring 工作原理及为什么要用