Chinaunix首页 | 论坛 | 博客
  • 博客访问: 97209
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 194
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-26 22:04
个人简介

大家好,我叫王大锤!

文章分类

全部博文(21)

分类: C/C++

2015-05-03 10:00:40

 Netlink是套接字家族中的一员,主要用内核与用户空间的进程间、用户进程间的通讯。然而它并不像网络套接字可以用于主机间通讯,Netlink只能用于同一主机上进程通讯,并通过PID来标识它们。
Netlink被设计为在Linux内核与用户空间进程传送各种网络信息。网络工具iproute2利用 Netlink从用户空间与内核进行通讯。Netlink由一个在用户空间的标准的Socket接口和内核模块 提供的内核API组成。Netlink的设计比ioctl更加灵活,Netlink使用了AF_NETLINK Socket 家族。
RFC 3549详细的描述了Netlink协议。




  netlink的实际应用很多,包括大家熟知的udev也是用的netlink方式。所以学习下netlink很有必要。


资料名称: netlink socket 编程之 why & how
内容简介: 此文章是翻译国外的一个权威文章,维基百科上首推。优点是介绍详细全面,缺点是
             文章比较老,此原创文章在2005年写的,但作为netlink的入门学习非常好。
文章链接:


资料名称: Linux-3.2.0.24中内核的Netlink测试使用
内容简介: 此文章讲的是3.2的内核,由于不同的内核版本netlink的api创建方式是不同的,但原理相同。
             如果用这个版本内核的童鞋可以参考下。
文章链接:http://blog.csdn.net/wangpengqi/article/details/9969599


资料名称: netlink 学习笔记 3.8.13内核
内容简介: 此文章讲的是3.8的内核,这个内核还是比较新的,我看了下这个文章的对应的api和我笔记本
             上的3.10.10的api基本相同,所以想看新的netlink的api可以参考这个,缺点是这个文章没有
             完整的参考代码,如果有空我会补上的。
文章链接:http://www.cnblogs.com/D3Hunter/p/3207670.html


资料名称: 监听网卡的链路通断
内容简介: netlink的一个实际应用,监听网卡的up&down事件。通过这个可以同理写个地址变化监听的程序。
文章链接:http://blog.chinaunix.net/uid-317451-id-92692.html




内核3.10.10示例:
用户态:app.c

点击(此处)折叠或打开

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/socket.h>
  5. #include <sys/types.h>
  6. #include <string.h>
  7. #include <asm/types.h>
  8. #include <linux/netlink.h>
  9. #include <linux/socket.h>
  10. #include <errno.h>
  11.  
  12. #define NETLINK_TEST 25
  13. #define MAX_PAYLOAD 1024 // maximum payload size
  14.  
  15. int main(int argc, char* argv[])
  16. {
  17.     int state;
  18.     struct sockaddr_nl src_addr, dest_addr;
  19.     struct nlmsghdr *nlh = NULL;
  20.     struct iovec iov;
  21.     struct msghdr msg;
  22.     int sock_fd, retval;
  23.     int state_smg = 0;
  24.     // Create a socket
  25.  
  26.     sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TEST);
  27.     if(sock_fd == -1){
  28.         printf("error getting socket: %s", strerror(errno));
  29.         return -1;
  30.     }
  31.  
  32.     // To prepare binding
  33.  
  34.     memset(&msg,0,sizeof(msg));
  35.     memset(&src_addr, 0, sizeof(src_addr));
  36.     src_addr.nl_family = AF_NETLINK;
  37.     src_addr.nl_pid = getpid(); // self pid
  38.  
  39.     src_addr.nl_groups = 0; // multi cast
  40.  
  41.  
  42.     retval = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
  43.     if(retval < 0){
  44.         printf("bind failed: %s", strerror(errno));
  45.         close(sock_fd);
  46.         return -1;
  47.     }
  48.  
  49.     // To prepare recvmsg
  50.  
  51.     nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
  52.     if(!nlh){
  53.         printf("malloc nlmsghdr error!\n");
  54.         close(sock_fd);
  55.         return -1;
  56.     }
  57.  
  58.     memset(&dest_addr,0,sizeof(dest_addr));
  59.     dest_addr.nl_family = AF_NETLINK;
  60.     dest_addr.nl_pid = 0;
  61.     dest_addr.nl_groups = 0;
  62.  
  63.     nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
  64.     nlh->nlmsg_pid = getpid();
  65.     nlh->nlmsg_flags = 0;
  66.     strcpy(NLMSG_DATA(nlh),"Hello you!");
  67.  
  68.     iov.iov_base = (void *)nlh;
  69.   iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
  70.     // iov.iov_len = nlh->nlmsg_len;
  71.  
  72.     memset(&msg, 0, sizeof(msg));
  73.     
  74.     msg.msg_name = (void *)&dest_addr;
  75.     msg.msg_namelen = sizeof(dest_addr);
  76.     msg.msg_iov = &iov;
  77.     msg.msg_iovlen = 1;
  78.  
  79.     printf("state_smg\n");
  80.     state_smg = sendmsg(sock_fd,&msg,0);
  81.  
  82.     if(state_smg == -1){
  83.         printf("get error sendmsg = %s\n",strerror(errno));
  84.     }
  85.  
  86.     memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD));
  87.     printf("waiting received!\n");
  88.     // Read message from kernel
  89.   state = recvmsg(sock_fd, &msg, 0);
  90.   if(state<0){
  91.     printf("state<1");
  92.   }
  93.   printf("Received message: %s\n",(char *) NLMSG_DATA(nlh));
  94.   close(sock_fd);
  95.  
  96.     return 0;
  97. }

内核态: netlink.c


点击(此处)折叠或打开

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/timer.h>
  4. #include <linux/time.h>
  5. #include <linux/types.h>
  6. #include <net/sock.h>
  7. #include <net/netlink.h>
  8.  
  9. #define NETLINK_TEST 25
  10. #define MAX_MSGSIZE 1024
  11. int pid;
  12. int err;
  13. struct sock *nl_sk = NULL;
  14. int flag = 0;
  15.  
  16. int stringlength(const char *s)
  17. {
  18.   int slen = 0;
  19.   for(; *s; s++){
  20.     slen++;
  21.   }
  22.   return slen;
  23. }
  24.  
  25. void sendnlmsg(void)
  26. {
  27.   struct sk_buff *skb_1;
  28.   struct nlmsghdr *nlh;
  29.   int len = NLMSG_SPACE(MAX_MSGSIZE);
  30.   int slen = 0;
  31.   char buffer[128];
  32.   const char *message="hello i am kernel";
  33.   if(!message || !nl_sk){
  34.     return ;
  35.   }
  36.   skb_1 = alloc_skb(len,GFP_KERNEL);
  37.   if(!skb_1){
  38.     printk(KERN_ERR "my_net_link:alloc_skb_1 error\n");
  39.   }
  40.   nlh = nlmsg_put(skb_1,0,0,0,MAX_MSGSIZE,0);
  41.  
  42.   //NETLINK_CB(skb_1).pid = 0;
  43.   NETLINK_CB(skb_1).dst_group = 0;
  44.  
  45.   slen = stringlength(message);
  46.   memset(buffer,0,sizeof(buffer));
  47.   memcpy(buffer,message,slen);
  48.   memcpy(NLMSG_DATA(nlh),buffer,slen+1);
  49.   printk("my_net_link:send message '%s'.\n",(char *)NLMSG_DATA(nlh));
  50.  
  51.   netlink_unicast(nl_sk,skb_1,pid,MSG_DONTWAIT);
  52. }
  53.  
  54. void nl_data_ready(struct sk_buff *__skb)
  55. {
  56.   struct sk_buff *skb;
  57.   struct nlmsghdr *nlh;
  58.   char str[100];
  59.   struct completion cmpl;
  60.   int i=10;
  61.   skb = skb_get (__skb);
  62.   if(skb->len >= NLMSG_SPACE(0)){
  63.     nlh = nlmsg_hdr(skb);
  64.  
  65.     memcpy(str, NLMSG_DATA(nlh), sizeof(str));
  66.     printk("Message received:%s\n",str) ;
  67.     pid = nlh->nlmsg_pid;
  68.     while(i--){
  69.       //init_completion(&cmpl);
  70.       //wait_for_completion_timeout(&cmpl,3 * HZ);
  71.       sendnlmsg();
  72.       break;
  73.     }
  74.     flag = 1;
  75.     kfree_skb(skb);
  76.   }
  77.  
  78. }
  79.  
  80. // Initialize netlink
  81.  
  82. /*
  83.   kernel 3.9.6中实例代码
  84.  
  85.   struct netlink_kernel_cfg {
  86.   unsigned int groups;
  87.   unsigned int flags;
  88.   void (*input)(struct sk_buff *skb);
  89.   struct mutex *cb_mutex;
  90.   void (*bind)(int group);
  91.   };
  92.  
  93.   netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
  94.  
  95.   3.2.0-24中
  96.   struct sock *netlink_kernel_create(struct net *net,
  97.   int unit,unsigned int groups,
  98.   void (*input)(struct sk_buff *skb),
  99.   struct mutex *cb_mutex,
  100.   struct module *module);
  101.   */
  102.  
  103. static int netlink_init(void)
  104. {
  105.   struct netlink_kernel_cfg cfg = {
  106.     .input = nl_data_ready,//该函数原型可参考内核代码,其他参数默认即可,可参考内核中的调用
  107.   };
  108.  
  109.   nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, &cfg);
  110.  
  111.   if(!nl_sk){
  112.     printk(KERN_ERR "my_net_link: create netlink socket error.\n");
  113.     return 1;
  114.   }
  115.  
  116.   printk("my_net_link_3: create netlink socket ok.\n");
  117.   return 0;
  118. }
  119.  
  120. static void netlink_exit(void)
  121. {
  122.   if(nl_sk != NULL){
  123.     sock_release(nl_sk->sk_socket);
  124.   }
  125.  
  126.   printk("my_net_link: self module exited\n");
  127. }
  128.  
  129. module_init(netlink_init);
  130. module_exit(netlink_exit);
  131.  
  132. MODULE_AUTHOR("");
  133. MODULE_LICENSE("GPL");

Makefile:

点击(此处)折叠或打开

  1. obj-m := netlink.o
  2. KERNELBUILD := /lib/modules/`uname -r`/build
  3. default:
  4.   make -C $(KERNELBUILD) M=$(shell pwd) modules
  5. clean:
  6.   rm -rf *.o .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers .*.d *.unsigned *.order
关键词解释:

协议族 
  是一组协议的集合。
协议栈
  是协议的实现。
地址族
  是地址划分的标准集合。
阅读(1651) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~