linux下的netlink编程
时间:2010-12-23 来源:空灵静世
1.创建文件:net_link.c
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/socket.h>
#include <linux/types.h>
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <net/sock.h>
struct sock *nl_sk = NULL;
static void nl_data_ready (struct sock *sk, int len)
{
wake_up_interruptible(sk->sk_sleep);
}
int netlink_test()
{
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh = NULL;
int err;
u32 pid;
nl_sk = netlink_kernel_create(28, 0, nl_data_ready, THIS_MODULE);
if (!nl_sk)
{
printk("Fail to create lc user event netlink socket.\n");
return 0;
}
/* wait for message coming down from user-space */
skb = skb_recv_datagram(nl_sk, 0, 0, &err);
nlh = (struct nlmsghdr *)skb->data;
printk("%s: received netlink message payload:%s ",__FUNCTION__,NLMSG_DATA(nlh));
pid = nlh->nlmsg_pid;
// skb_put(skb,strlen(" from kernet"));
// strcpy(NLMSG_DATA(nlh), "from kernet");
nlh->nlmsg_len = skb->len;
NETLINK_CB(skb).pid = 0;
NETLINK_CB(skb).dst_pid = pid;
NETLINK_CB(skb).dst_group = 1;
netlink_broadcast(nl_sk, skb, 0, 1, GFP_KERNEL);
return 1;
}
static int __init my_module_init(void)
{
printk( "Initializing Netlink Socket\n");
if( netlink_test())
{
printk( "Message has send\n");
}
else
{
printk("send error\n");
}
return 0;
}
static void __exit my_module_exit(void)
{
if(nl_sk)
{
sock_release(nl_sk->sk_socket);
printk( "Goodbye\n");
}
else
{
printk( "no sock,release error\n");
}
}
module_init(my_module_init);
module_exit(my_module_exit);
2.创建 sender.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <sys/select.h>
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl saddr, daddr;
struct msghdr msg;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sd;
int main()
{
sd = socket(PF_NETLINK, SOCK_RAW,28);
if (sd == -1)
{
perror("socket error\n");
exit(1);
}
memset(&saddr, 0, sizeof(saddr));
memset(&daddr, 0, sizeof(daddr));
saddr.nl_family = AF_NETLINK;
saddr.nl_pid = getpid();
saddr.nl_groups = 1;//
bind(sd, (struct sockaddr*)&saddr, sizeof(saddr));
daddr.nl_family = AF_NETLINK;
daddr.nl_pid = 0;
daddr.nl_groups = 1;
nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
/* Fill the netlink message header */
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid(); /* self pid */
nlh->nlmsg_flags = 0;
/* Fill in the netlink message payload */
strcpy(NLMSG_DATA(nlh), "crazysummers call kerbel!\n");
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&daddr;
msg.msg_namelen = sizeof(daddr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Sent message to kernel\n");
sendmsg(sd, &msg, 0);
printf("Waiting for message from kernel\n");
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
recvmsg(sd, &msg, 0);
printf(" Received message from kernel that send to it: %s \n", NLMSG_DATA(nlh));
/* Close Netlink Socket */
close(sd);
}
3.创建Makefile
MODULE_NAME :=net_link
obj-m+=$(MODULE_NAME).o
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD)
gcc -g -o sender sender.c
clean:
rm -f *.ko *.o *.cmd sender $(MODULE_NAME).mod.c Module.symvers
in:
insmod net_link.ko
rm:
rmmod net_link
sp:
cat /proc/net/netlink
ru:
./sender
sm:
dmesg -c
4.这几个文件都放到一个文件夹中,执行:
(1)make
(2)make sm (清理内核打印信息)
(3) make in (这步将内核模块加载到内核)
(4)打开一个终端 ctrl+shift+n, 运行 make rn
(5)通讯完毕,运行 make sm 查看内核的打印信息
(6)运行完毕 执行 make rm 和 make clean 进行清理
更多的例子请看http://blog.csdn.net/dipperkun/archive/2007/12/19/1953526.aspx 不过需要该其中的错误