netlink测试程序的编写

12 篇文章 0 订阅

有幸看到文章的童鞋,送上一句话。

linux内核的编程遥遥无期,也不知到何时才是头,至少我们知道未来是光明的,而且也为解决的每一个问题感到兴奋无比。


下面是我查找大牛的相关netlink详解和代码,重新写了一遍,也想大家能自己写一遍,熟悉一下流程。

the kernel moduule:

/*
*                    how to program use netlink to communicate
*                    between the kernel space and the user spaece 
*                                                         by:dead_angel
*                                                       date:Apr.19,2013
*/


/*
*                        the kernel space module.             */
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/module.h>
#include<net/netlink.h>
#include<net/sock.h>

#define NETLINK_TEST 25  /*VALUE>16*/
#define MAXMSGSIZE 1024


int pid = 0;
int flag = 0;
struct sock* sock = NULL;


/* send the message */
void nl_sendmsg(char * msg)
{
  //1)declare a struct sk_buff*
  //2)declare a struct nlmsghdr *
  //3)call alloc_skb() to alloc the struct skb_buff 
  //4)appenxid the struct nlmsg to the tail of the struct skb_buff
  //5)get the nlmsghdt ponit to the field of the struct skb_buff
  //6)init the fiels of the nlmsg
  //7)insrt the meg into the mlmsg
  //8)call the netlink_unicast() to transmit the struct skb_buff
  struct sk_buff * skbuftmp = NULL;
  struct nlmsghdr* nlh = NULL; 
  unsigned int len_msg = 0;
  //len_msg = get_len(msg);
  len_msg=strlen(msg);
  int len = NLMSG_SPACE(MAXMSGSIZE);
  if(!msg&&!sock)
    {
      return ;
    }
  skbuftmp = alloc_skb(len,GFP_KERNEL);
  if(!skbuftmp)
    {
      printk("alloc_skb();failed!\n"); 
      return ;
    }
  nlh = nlmsg_put(skbuftmp,0,0,0,MAXMSGSIZE,0);
  NETLINK_CB(skbuftmp).pid = 0;
  NETLINK_CB(skbuftmp).dst_group = 0;
  msg[len_msg] = '\0';
  
  memcpy(NLMSG_DATA(nlh),msg,len_msg+1);
  printk("the send str = %s \n ", (char*)NLMSG_DATA(nlh));
  netlink_unicast(sock,skbuftmp,pid,MSG_DONTWAIT);
}

/*the callback function */

void  nl_data_ready(struct sk_buff* skbuf)
{
  struct completion cmpl;
  struct nlmsghdr* nlh = NULL;
  struct sk_buff * skbbuftmp = skb_get(skbuf);
  if(skbbuftmp->len>=NLMSG_SPACE(0))
    {
      /* point to the nlmsg */
      nlh = nlmsg_hdr(skbbuftmp);
      char buf[MAXMSGSIZE] = "";
      memcpy(buf,NLMSG_DATA(nlh),MAXMSGSIZE);
      printk("the get msg = %s",buf);
      pid = nlh->nlmsg_pid;
    
      int i = 10;
      while(i--)
          {
             init_completion(&cmpl);
             wait_for_completion_timeout(&cmpl,3*HZ);
             nl_sendmsg("this is a kernel program which use the netlink to communicate with the user space !\n");
             printk("send ok !\n");
          }
      flag = 1;
      kfree_skb(skbbuftmp);
    }
}


/* the module init */
static int netlink_init(void)
{
  printk("the netlink test!\n");
  sock = netlink_kernel_create(&init_net,NETLINK_TEST,1,nl_data_ready,NULL,THIS_MODULE);
  return 0;
}

/* the module exit */
static void netlink_exit(void)
{
  if(sock!=NULL)
    {
     sock_release(sock->sk_socket);
    }
  printk("quit the netlink test!\n");
}


module_init(netlink_init);
module_exit(netlink_exit);

MODULE_AUTHOR("dead_angel");
MODULE_LICENSE("GPL");

the user program:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<linux/socket.h>
#include<linux/netlink.h>

#define NETLINK_TEST 25
#define MAX_PAYLOAD  1024


void main()
{
   /* create the socket */
   unsigned int sock = socket(AF_NETLINK,SOCK_RAW,NETLINK_TEST);
   if(sock==-1)
     {
       printf("create the socket frailed!\n");
       return ;
     }

   /* init the src addr */
   struct sockaddr_nl  src,dst;
   memset(&src,0,sizeof(struct sockaddr_nl));
   src.nl_family = AF_NETLINK;
   src.nl_pid = getpid();
   src.nl_groups = 0;
   if(bind(sock,(struct sockaddr*)&src,sizeof(struct sockaddr_nl))<0)
     {
        printf("bind failed!\n");
        close(sock);
        return ;
     }

   /* init the dst addr */
   memset(&dst,0,sizeof(struct sockaddr_nl));
   dst.nl_family = AF_NETLINK;
   dst.nl_pid = 0;
   dst.nl_groups = 0;   

   /* create the netlink packet */
   struct nlmsghdr* nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
   if(nlh == NULL)
     {
        printf("malloc failed!\n");
        close(sock);
        return;
     }
   nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
   nlh->nlmsg_pid = getpid(); 
   nlh->nlmsg_flags = 0;
   strcpy(NLMSG_DATA(nlh),"hello! the kernel module!\n");
  
   struct iovec iov;
   memset(&iov,0,sizeof(struct iovec));
   iov.iov_base = (void*)nlh;
   iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
  
   struct msghdr msgh;
   memset(&msgh,0,sizeof(struct msghdr));
   msgh.msg_name = (void*)&dst;
   msgh.msg_namelen = sizeof(struct sockaddr_nl);
   msgh.msg_iov = &iov;
   msgh.msg_iovlen = 1;

   printf("send msg to kernel!\n");
   if(sendmsg(sock,&msgh,0)==-1)
     {
       printf("send failed!\n");
       close(sock);
       return;
     } 
   
   memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD));
   printf("begin to recv msg!\n");
   while(1)
        { 
          if(recvmsg(sock,&msgh,0)!=-1)
            {
              printf("msg = %s\n",(char*)NLMSG_DATA(nlh));
            }
        }    

   close(sock);
   return ;    
}

the Makefile:

obj-m := netlink_kernel.o
KERNELBUILD := /lib/modules/`uname -r`/build 
default: 
	@echo "BUILE Kmod" 
	@make -C $(KERNELBUILD) M=$(shell pwd) modules 
	gcc -o netlink_user netlink_user.c 
clean: 
	@echo " CLEAN kmod" 
	@rm -rf *.o 
	@rm -rf .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers .*.d


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NetlinkLinux 内核提供的一种机制,用于内核与用户空间之间的通信。通过 Netlink,应用程序可以向内核发送请求,并接收内核的相应信息。 使用 Netlink 与应用程序通信需要以下步骤: 1. 创建 Netlink socket:使用 `socket()` 系统调用创建一个 Netlink socket。 2. 绑定 Netlink socket:使用 `bind()` 系统调用将 Netlink socket 绑定到一个本地地址上。 3. 发送请求:使用 `sendmsg()` 系统调用向内核发送请求消息。 4. 接收响应:使用 `recvmsg()` 系统调用从 Netlink socket 接收响应消息。 5. 处理响应:对接收到的响应消息进行解析和处理。 下面是一个简单的示例代码,演示如何使用 Netlink 与内核模块进行通信: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <linux/netlink.h> #define NETLINK_USER 31 #define MAX_PAYLOAD 1024 /* maximum payload size*/ struct nlmsg { struct nlmsghdr hdr; char data[MAX_PAYLOAD]; }; int main(int argc, char **argv) { int sock_fd; struct sockaddr_nl src_addr, dest_addr; struct nlmsg msg; struct iovec iov; struct msghdr mh; /* create netlink socket */ sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_USER); if (sock_fd < 0) { perror("socket"); return -1; } /* initialize source address */ memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); /* bind netlink socket */ if (bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0) { perror("bind"); close(sock_fd); return -1; } /* initialize destination address */ memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0; /* kernel */ dest_addr.nl_groups = 0; /* unicast */ /* initialize netlink message */ memset(&msg, 0, sizeof(msg)); msg.hdr.nlmsg_len = NLMSG_LENGTH(strlen("Hello, kernel!") + 1); msg.hdr.nlmsg_type = 1; msg.hdr.nlmsg_flags = NLM_F_REQUEST; strcpy(msg.data, "Hello, kernel!"); /* initialize iovec */ iov.iov_base = &msg.hdr; iov.iov_len = msg.hdr.nlmsg_len; /* initialize msghdr */ memset(&mh, 0, sizeof(mh)); mh.msg_name = &dest_addr; mh.msg_namelen = sizeof(dest_addr); mh.msg_iov = &iov; mh.msg_iovlen = 1; /* send netlink message */ if (sendmsg(sock_fd, &mh, 0) < 0) { perror("sendmsg"); close(sock_fd); return -1; } /* receive netlink message */ memset(&msg, 0, sizeof(msg)); iov.iov_base = &msg; iov.iov_len = sizeof(msg); if (recvmsg(sock_fd, &mh, 0) < 0) { perror("recvmsg"); close(sock_fd); return -1; } /* print netlink message */ printf("Received message: %s\n", msg.data); close(sock_fd); return 0; } ``` 在上面的示例中,我们首先创建了一个 Netlink socket,并将其绑定到一个本地地址上。然后,我们使用 `sendmsg()` 向内核发送一个请求消息,该消息包含一个字符串 "Hello, kernel!"。最后,我们使用 `recvmsg()` 接收内核的响应消息,并将其打印出来。 当然,这只是一个简单的示例,实际使用中可能需要更复杂的消息格式和处理逻辑。但是,基本的 Netlink 通信流程和 API 调用方式应该是类似的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值