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

好好学习天天向上

文章分类

全部博文(24)

文章存档

2018年(1)

2016年(7)

2015年(6)

2014年(10)

我的朋友

分类: LINUX

2014-10-24 12:25:55

    参考了netlink学习的一篇博文,讲得简单明了,地址如下:netlink socket编程之why & how。但是不大清楚此博文基于的内核版本是什么,和我现在实际项目中的内核版本函数参数有出入,以下的例子是在linux 3.4rt版本上写的netlink通信程序,从具体项目中摘录,有些函数是平台特有的。

    内核向用户态发送消息,传送一组数据,用户态接收到数据。
   
    内核态程序:

点击(此处)折叠或打开

  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/types.h>
  4. #include <linux/sched.h>
  5. #include <net/sock.h>
  6. #include <linux/netlink.h>

  7. //linux 3.4rt

  8. #define SSK_NETLINK_MONITOR (25)


  9. static struct sock *g_monitor_nl_sk;


  10. /*
  11. 通过在应用层SSK中用ret = HAL_sysSetMonitorFd(getpid())调用将ssk的进程id传送到kernel中。
  12. VOS_RET_E HAL_sysSetMonitorFd(UINT32 pid)
  13. {
  14.     return hal_sysBoardIoctl(BOARD_IOCTL_SET_MONITOR_FD, 0, "", 0, pid, "");
  15. }
  16. //kernel ioctl接收sskpid
  17. static int board_ioctl( struct inode *inode, struct file *flip,
  18.                        unsigned int command, unsigned long arg )
  19. {
  20.     case BOARD_IOCTL_SET_MONITOR_FD:
  21.     if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {

  22.        g_monitor_nl_pid = ctrlParms.offset;
  23.        printk(KERN_INFO "monitor task is initialized pid= %d \n",g_monitor_nl_pid);
  24.     }
  25.     break;
  26. }*/
  27. static int g_monitor_nl_pid = 0 ;

  28. typedef enum
  29. {
  30.     HAL_BTN_NAME_RESET,
  31.     HAL_BTN_NAME_WLAN,
  32.     HAL_BTN_NAME_WPS,
  33.     HAL_BTN_NAME_TURN,
  34.     HAL_BTN_NAME_PWROFFALLLED, /* Spark.Lei added on 2013-10-14 */
  35.     HAL_BTN_NAME_END
  36. } HAL_BTN_NAME_E;

  37. typedef struct
  38. {
  39.     HAL_BTN_NAME_E name;
  40.     unsigned int duration;
  41. } HAL_BTN_MSG_BODY_T;



  42. /*functionto receive message from usersapce
  43.  * Currently we dont expect any messages fromm userspace
  44.  */
  45. void kerSysRecvFrmMonitorTask(struct sk_buff *skb)
  46. {

  47.    /*process the message here*/
  48.    printk(KERN_WARNING "unexpected skb received at %s \n",__FUNCTION__);
  49.    kfree_skb(skb);
  50.    return;
  51. }

  52. void kerSysInitMonitorSocket( void )
  53. {
  54.    g_monitor_nl_sk = netlink_kernel_create(&init_net, NETLINK_BRCM_MONITOR, 0, kerSysRecvFrmMonitorTask, NULL, THIS_MODULE);

  55.    if(!g_monitor_nl_sk)
  56.    {
  57.       printk(KERN_ERR "Failed to create a netlink socket for monitor\n");
  58.       return;
  59.    }

  60. }

  61. void kerSysSendtoMonitorTask(int msgType, char *msgData, int msgDataLen)
  62. {

  63.    struct sk_buff *skb = NULL;
  64.    struct nlmsghdr *nl_msgHdr = NULL;
  65.    unsigned int payloadLen =sizeof(struct nlmsghdr);

  66.    if(!g_monitor_nl_pid)
  67.    {
  68.       //printk(KERN_INFO "message received before monitor task is initialized type %d %s \n",msgType,__FUNCTION__);
  69.       return;
  70.    }

  71.    if(msgData && (msgDataLen > MAX_PAYLOAD_LEN))
  72.    {
  73.       printk(KERN_ERR "invalid message len in %s",__FUNCTION__);
  74.       return;
  75.    }

  76.    payloadLen += msgDataLen;
  77.    payloadLen = NLMSG_SPACE(payloadLen);

  78.    /*Alloc skb ,this check helps to call the fucntion from interrupt context */

  79.    if(in_atomic())
  80.    {
  81.       skb = alloc_skb(payloadLen, GFP_ATOMIC);
  82.    }
  83.    else
  84.    {
  85.       skb = alloc_skb(payloadLen, GFP_KERNEL);
  86.    }

  87.    if(!skb)
  88.    {
  89.       printk(KERN_ERR "failed to alloc skb in %s",__FUNCTION__);
  90.       return;
  91.    }

  92.    nl_msgHdr = (struct nlmsghdr *)skb->data;
  93.    nl_msgHdr->nlmsg_type = msgType;
  94.    nl_msgHdr->nlmsg_pid=0;/*from kernel */
  95.    nl_msgHdr->nlmsg_len = payloadLen;
  96.    nl_msgHdr->nlmsg_flags =0;

  97.    if(msgData)
  98.    {
  99.       memcpy(NLMSG_DATA(nl_msgHdr),msgData,msgDataLen);
  100.    }

  101.    NETLINK_CB(skb).pid = 0; /*from kernel */

  102.    skb->len = payloadLen;

  103.    netlink_unicast(g_monitor_nl_sk, skb, g_monitor_nl_pid, MSG_DONTWAIT);
  104.    return;
  105. }

  106. void kerSysCleanupMonitorSocket(void)
  107. {
  108.    g_monitor_nl_pid = 0 ;
  109.    sock_release(g_monitor_nl_sk->sk_socket);
  110. }


  111. main()
  112. {
  113.     HAL_BTN_MSG_BODY_T btn_msg;
  114.     
  115.     btn_msg.name = HAL_BTN_NAME_WLAN;
  116.     btn_msg.duration = 0;

  117.     kerSysInitMonitorSocket();
  118.     kerSysSendtoMonitorTask(MSG_NETLINK_BTN_DOWN, (char *)&btn_msg, sizeof(btn_msg));
  119.     
  120.     kerSysCleanupMonitorSocket();
  121.     
  122. }
    用户态接收程序:

点击(此处)折叠或打开

  1. #include <sys/stat.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <sys/socket.h>
  6. #include <sys/types.h>
  7. #include <string.h>
  8. #include <asm/types.h>
  9. #include <linux/netlink.h>
  10. #include <linux/socket.h>


  11. #define SSK_NETLINK_MONITOR (25)

  12. static int sg_kernelMonitorFd = UTIL_INVALID_FD;


  13. VOS_RET_E HAL_sysSetMonitorFd(UINT32 pid)
  14. {
  15.     return hal_sysBoardIoctl(BOARD_IOCTL_SET_MONITOR_FD, 0, "", 0, pid, "");
  16. }


  17. /* opens a netlink socket and intiliaze it to recieve messages from
  18.  * kernel for protocol SSK_NETLINK_MONITOR
  19.  */
  20. static VOS_RET_E ssk_initKernelMonitorFd(void)
  21. {
  22.     VOS_RET_E ret = VOS_RET_SUCCESS;
  23.     struct sockaddr_nl addr;

  24.     sg_kernelMonitorFd = socket(AF_NETLINK, SOCK_RAW, SSK_NETLINK_MONITOR);
  25.     if (sg_kernelMonitorFd < 0)
  26.     {
  27.         vosLog_error("Could not open netlink socket for kernel monitor");
  28.         return VOS_RET_INTERNAL_ERROR;
  29.     }
  30.     else
  31.     {
  32.         vosLog_debug("sg_kernelMonitorFd=%d", sg_kernelMonitorFd);
  33.     }

  34.     addr.nl_family = AF_NETLINK;
  35.     addr.nl_pid = getpid();
  36.     addr.nl_groups = 0;

  37.     if (bind(sg_kernelMonitorFd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  38.     {
  39.         vosLog_error("Could not bind netlink socket for kernel monitor");
  40.         close(sg_kernelMonitorFd);
  41.         sg_kernelMonitorFd = UTIL_INVALID_FD;
  42.         return VOS_RET_INTERNAL_ERROR;
  43.     }

  44.     /*send the pid of ssk to kernel,so that it can send events */
  45.     ret = HAL_sysSetMonitorFd(getpid());
  46.     if (ret == VOS_RET_SUCCESS)
  47.     {
  48.         vosLog_debug("registered fd %d with kernel monitor", sg_kernelMonitorFd);
  49.     }
  50.     else
  51.     {
  52.         vosLog_error("failed to register fd %d with kernel monitor, ret=%d", sg_kernelMonitorFd, ret);
  53.         close(sg_kernelMonitorFd);
  54.         sg_kernelMonitorFd = UTIL_INVALID_FD;
  55.     }

  56.     return ret;
  57. }




  58. /** Receive and process messages sent from kernel on netlink sockets
  59.   *
  60.   */
  61. static void ssk_processKernelMonitor(void)
  62. {
  63.     int recvLen = 0;
  64.     char buf[4096] = {0};
  65.     struct iovec iov = {buf, sizeof(buf)};
  66.     struct sockaddr_nl nl_srcAddr;
  67.     struct msghdr msg;
  68.     struct nlmsghdr *nl_msgHdr = NULL;
  69.     VOS_RET_E ret = VOS_RET_SUCCESS;
  70.     UBOOL8 isLinkUp = 0;
  71.  
  72.     memset(&msg, 0, sizeof(struct msghdr));
  73.     msg.msg_name = (void *)&nl_srcAddr;
  74.     msg.msg_namelen = sizeof(nl_srcAddr);
  75.     msg.msg_iov = &iov;
  76.     msg.msg_iovlen = 1;

  77.     vosLog_debug("Enter\n");

  78.     recvLen = recvmsg(sg_kernelMonitorFd, &msg, 0);
  79.     if (recvLen < 0)
  80.     {
  81.         if (errno == EWOULDBLOCK || errno == EAGAIN)
  82.         {
  83.             return;
  84.         }

  85.         /* Anything else is an error */
  86.         vosLog_error("read_netlink: Error recvmsg: %d\n", recvLen);
  87.         perror("read_netlink: Error: ");
  88.         return;
  89.     }

  90.     if (recvLen == 0)
  91.     {
  92.         vosLog_error("read_netlink: EOF\n");
  93.     }

  94.     /* There can be more than one message per recvmsg */
  95.     for (nl_msgHdr = (struct nlmsghdr *)buf;
  96.             NLMSG_OK(nl_msgHdr, (unsigned int)recvLen);
  97.             nl_msgHdr = NLMSG_NEXT(nl_msgHdr, recvLen))
  98.     {
  99.         /* Finish reading */
  100.         if (nl_msgHdr->nlmsg_type == NLMSG_DONE)
  101.         {
  102.             return;
  103.         }

  104.         /* Message is some kind of error */
  105.         if (nl_msgHdr->nlmsg_type == NLMSG_ERROR)
  106.         {
  107.             vosLog_error("read_netlink: Message is an error \n");
  108.             return; // Error
  109.         }

  110.         /*Currently we expect messages only from kernel, make sure
  111.          * the message is from kernel
  112.          */
  113.         if (nl_msgHdr->nlmsg_pid != 0)
  114.         {
  115.             vosLog_error("netlink message source(%d)is not kernel", nl_msgHdr->nlmsg_pid);
  116.             return;
  117.         }

  118.         vosLog_debug("ssk receive kernel msg type:0x%x",nl_msgHdr->nlmsg_type);

  119.         switch (nl_msgHdr->nlmsg_type)
  120.         {
  121.             case MSG_NETLINK_ADD_RT_NOTIFY:
  122.             {
  123.                 vosLog_error("received MSG_NETLINK_ADD_RT_NOTIFY");
  124.                 //vosLog_debug("received MSG_NETLINK_ADD_RT_NOTIFY");
  125.                 unsigned int ipaddr = *(unsigned int *)(nl_msgHdr + 1);
  126.                 printf("\nip addr int = %x",ipaddr);
  127.                 
  128.                 UTIL_DO_SYSTEM_ACTION("route add %d.%d.%d.%d dev br1", ((unsigned char*)&ipaddr)[0],((unsigned char*)&ipaddr)[1],((unsigned char*)&ipaddr)[2],((unsigned char*)&ipaddr)[3]);
  129.                 break;
  130.             }
  131.             
  132.             default:
  133.                 vosLog_error(" Unknown netlink nlmsg_type %d\n",
  134.                          nl_msgHdr->nlmsg_type);
  135.                 break;
  136.         }
  137.     }

  138.     vosLog_debug("Exit\n");
  139.     return;
  140. }


  141. void main(void)
  142. {
  143.     ssk_initKernelMonitorFd();
  144.     while(1)
  145.     {
  146.         if (FD_ISSET(sg_kernelMonitorFd, &readFds))
  147.         {
  148.             ssk_processKernelMonitor();
  149.         }
  150.     }
  151.     if (sg_kernelMonitorFd != UTIL_INVALID_FD)
  152.     {
  153.         close(sg_kernelMonitorFd);
  154.     }
  155. }


阅读(4071) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:变量在不同进程中是相互独立的一个例子

给主人留下些什么吧!~~