有幸看到文章的童鞋,送上一句话。
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