免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1532 | 回复: 1
打印 上一主题 下一主题

[网络子系统] 刚学netlink,第一次写netlink程序,有些疑问 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-09-26 16:41 |只看该作者 |倒序浏览
主要的目的是用户态发送消息给内核,内核回复消息给用户态。
我内核尝试了用2种方式回复。
一种是正常的处理,另一种是用kernel_thread一个线程,然后这个线程处理。
前一种用户态能正常收到,后一种用户态收不到数据,不知道问题在哪里。

  1. 用户态程序:
  2. int main()
  3. {
  4.        
  5.     struct sockaddr_nl src_addr;
  6.     s32 ret;

  7.    //我用自己的结构以体
  8.     struct struReq_s
  9.         {
  10.                 int pid;         //存放当前进程的pid,内核回复消息的时候需要
  11.                 int data_len;
  12.                 char data[0];
  13.         };

  14.    u8 buf[1024] = {0};//存放内核传回的数据

  15.     struct struReq_s *struReq = NULL;
  16.     netlink_socket = socket(AF_NETLINK, SOCK_RAW, NL_ADX);
  17.     if(netlink_socket < 0)
  18.     {
  19.         return -1;
  20.     }

  21.     memset(&src_addr, 0, sizeof(src_addr));
  22.     src_addr.nl_family = AF_NETLINK;
  23.     src_addr.nl_pid = getpid();
  24.     src_addr.nl_groups = 1;
  25.                
  26.     ret = bind(netlink_socket, (struct sockaddr *)&src_addr, sizeof(src_addr));
  27.     if(ret < 0)
  28.     {
  29.         return -1;
  30.     }


  31.         struReq = malloc(sizeof( struct struReq_s) + 10);
  32.         if(struReq == NULL)
  33.         {
  34.                 printf("malloc fail\n");
  35.                 return 0;
  36.         }
  37.         memset(struReq, 0, sizeof(struct struReq_s) +  10);

  38.         struReq->pid = getpid();
  39.         struReq->data_len  = 10;
  40.         memcpy(struReq->data,"nihao",strlen("nihao"));
  41.        
  42.         memset(&src_addr, 0, sizeof(src_addr));       
  43.         src_addr.nl_family = AF_NETLINK;       
  44.         src_addr.nl_pid = 0;       
  45.         src_addr.nl_groups = 0;
  46.    
  47.             // 发送消息给内核
  48.         if(sendto(netlink_socket, struReq, struReq->data_len + sizeof(struct struReq_s), 0,               
  49.                 (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0)       
  50.         {
  51.                 return -1;         
  52.         }
  53.        
  54.         printf("user recv\n");
  55.         /*阻塞的读*/
  56.         recv(netlink_socket,buf,1024,0);
  57.         printf("recv from kernel len : %d\n",((struct struReq_s *)buf)->data_len);
  58.         printf("recv from kernel data: %s\n",((struct struReq_s *)buf)->data);
  59.        
  60.         free(struReq);
  61.         return 0;
复制代码
在内核中我用2种方法回复,但是其中一个不行。
netlinkfd = netlink_kernel_create(&init_vrf, NL_ADX, 0, kernel_receive, NULL, THIS_MODULE);

可行的方法如下:

  1. void kernel_receive(struct sk_buff *skb)
  2. {
  3.         printk("#########recv###########\n");
  4.         process_message_thread(skb);
  5.         printk("#########leave###########\n");
  6. }
  7. int process_message_thread(void *arg)
  8. {
  9.         struct sk_buff *skb = (struct sk_buff *)(arg);
  10.        
  11.         struct struReq_s  *msg = (struct struReq_s *) skb->data;
  12.             
  13.             /*打印出用户态传来的数据*/
  14.         printk("kernel recv data:%s\n",msg->data);
  15.         printk("kernel recv pid :%d\n",msg->pid);

  16.              /*构造回复的数据*/
  17.         struct struReq_s *needtosend = kmalloc(sizeof(struct struReq_s) + strlen("niyehao"),GFP_KERNEL);
  18.         needtosend->data_len = strlen("niyehao");
  19.         memcpy(needtosend->data,"niyehao", needtosend->data_len);

  20.              /*构造回复用的skb*/
  21.         skb = alloc_skb(sizeof(struct struReq_s) + strlen("niyehao"), GFP_ATOMIC);
  22.         skb_put(skb,sizeof(struct struReq_s) + strlen("niyehao"));
  23.         memcpy(skb->data,needtosend,sizeof(struct struReq_s) + strlen("niyehao"));
  24.             
  25.              /*发出去*/
  26.         netlink_unicast(netlinkfd, skb, msg->pid, MSG_DONTWAIT);
  27.        
  28.         printk("kernel send over\n");
  29.              kfree(needtosend);
  30.         return 0;
  31. }
  32. 这个方法用户态recv的时候能收到数据,并且打印出来。
复制代码
但是这种方法不行:
  1. void kernel_receive(struct sk_buff *skb)
  2. {
  3.         printk("#########recv###########\n");
  4.         kernel_thread(process_message_thread, skb, CLONE_KERNEL);
  5.         printk("#########leave###########\n");
  6. }
复制代码
这个方法不行,用户态一直阻塞的在recv。
不知道哪位能帮兄弟解决一下疑惑

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2014-09-28 14:08 |只看该作者
打了调试信息吓我一跳:
在用kernel_thread的情况下,我新alloc_skb的data指针指向的地址,和入参旧的skbdata指向的地址是一样的。。

所以可否理解:
A线程创建B线程,A线程的skb当做B线程的入参,A线程skb的data指向的缓冲区被释放,所以B线程alloc_skb的skb指向的data就用之前的缓冲区了。

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP