- 论坛徽章:
- 0
|
最近应用需求需要实现一下硬盘、U盘、eSata备份的热插拔功能,内核对热插拔都以实现,但是怎么才能让应用层也能实时的知道有热插拔事件产生呢,刚开始想到的是用信号来实现异步通知,虽然已经实现,但是这种方法不太适用,不能将所有的热插拔事件统一起来,后来网上google了几篇关于netlink的文章,顺便做了下笔记。
Netlink提供了一种异步通讯方式,使用时与标准的socket API一样。
内核代码:
#include linux/module.h>
#include linux/types.h>
#include linux/init.h>
#include linux/kernel.h>
#include linux/netlink.h>
#include linux/net.h>
#include net/sock.h>
#include linux/delay.h>
#define NETLINK_EXAMPLE 20
#define PAYLOAD 1024
static struct sock *sk = NULL;
static int netlink_example_init(void)
{
struct sk_buff *skb;
char *str = "access kernel";
char *tmp;
int len;
sk = netlink_kernel_create(NETLINK_EXAMPLE,1,NULL,NULL,THIS_MODULE);
if(IS_ERR(sk)){
printk("netlink kernel create failde\n");
return -ENOMEM;
}
//这里必须先调用netlink_kernel_create函数,将NETLINK_EXAMPLE注册到内核,否则调用bind会失败
msleep(10000);
len = strlen(str) + 1;
skb = alloc_skb(len,GFP_KERNEL);
if(skb){
tmp = skb_put(skb,len);
sprintf(tmp,"%s",str);
NETLINK_CB(skb).dst_group = 1;
netlink_broadcast(sk,skb,0,1,GFP_KERNEL);
}
return 0;
}
static void netlink_example_exit(void)
{
if(sk)
sock_release(sk->sk_socket);
}
MODULE_LICENSE("GPL");
module_init(netlink_example_init);
module_exit(netlink_example_exit)
应用代码:
#include stdio.h>
#include stdlib.h>
#include string.h>
#include ctype.h>
#include sys/un.h>
#include sys/ioctl.h>
#include sys/socket.h>
#include linux/types.h>
#include linux/netlink.h>
#include errno.h>
#include unistd.h>
#include arpa/inet.h>
#include netinet/in.h>
#define NETLINK_EXAMPLE 20
static int init_sock()
{
int size = 1024;
int ret;
struct sockaddr_nl snl;
memset((void *)snl,0,sizeof(struct sockaddr_nl));
snl.nl_family = AF_NETLINK;
snl.nl_pid = getpid();
snl.nl_groups = 1;
int fd = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_EXAMPLE);//NETLINK_KOBJECT_UEVENT);
if (fd == -1)
{
perror("socket");
return -1;
}
ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
if(ret 0){
perror("setsockopt");
close(fd);
return -1;
}
ret = bind(fd, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));
if (ret 0)
{
perror("bind");
close(fd);
return -1;
}
return fd;
}
int main(int argc, char* argv[])
{
int fd = init_sock();
char buf[100] = {0};
printf("wait for kernel message\n");
recv(fd, &buf, sizeof(buf), 0);
printf("=====%s\n",buf);
return 0;
}
先加载.ko文件,在运行应用代码,结果如下
# insmod /home/drive/netlink.ko &
# /home/app/netlink &
# wait for kernel message
=====access kernel
内核对于热插拔的实现就是基于这种方式来实现异步通知应用层的,具体代码见/lib/kobject_uevent.c。
参考文章:
http://www.apps.ietf.org/rfc/rfc3549.html
http://www.linuxjournal.com/article/7356
http://www.ibm.com/developerworks/cn/linux/l-netlink/index.html
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/101879/showart_2180639.html |
|