免费注册 查看新帖 |

Chinaunix

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

netlink笔记 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-02-09 11:40 |只看该作者 |倒序浏览
    最近应用需求需要实现一下硬盘、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

论坛徽章:
0
2 [报告]
发表于 2012-02-29 13:33 |只看该作者
netlink记号

论坛徽章:
0
3 [报告]
发表于 2012-04-01 13:24 |只看该作者
不错的例子。

论坛徽章:
0
4 [报告]
发表于 2012-04-02 08:07 |只看该作者
花前月下, 不如花钱“日”下。

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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP