netlink学习笔记(二)

1、netlink_kernel_create()函数分析

/*
 *      We export these functions to other modules. They provide a
 *      complete set of kernel non-blocking support for message
 *      queueing.
 */
struct sock *
netlink_kernel_create(struct net *net, int unit, unsigned int groups,
                      void (*input)(struct sk_buff *skb),
                      struct mutex *cb_mutex, struct module *module)
//net参数是新引入的,可用&init_net。这个init_net结构体是在linux/net/core/net_namespace.c 中定义的,此外在linux/include/net/net_namespace.h中也有外部定义,直接作为参数使用
//即可。unit即netlink接口类型,有ROUTE,FIREWALL,IP6_FW,XFRM等,最大值为MAX_LINKS。groups为具体各种类型netlink接口中的组号。input是消息处理函数,只要用户程序发送一个NETLINK_TEST类型的netlink消息到内核的话,通过netlink_kernel_create()函数注册的回调函数input()都会被调用。cb_mutex和module都是新添加的参数,具体功能不了解。
{
        struct socket *sock;
        struct sock *sk;
        struct netlink_sock *nlk;
        unsigned long *listeners = NULL;

        BUG_ON(!nl_table);

    // unit范围检查
        if (unit < 0 || unit >= MAX_LINKS)
                return NULL;

    // 建立netlink的socket
        if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
                return NULL;

        /*
         * We have to just have a reference on the net from sk, but don't
         * get_net it. Besides, we cannot get and then put the net here.
         * So we create one inside init_net and the move it to net.
         */

    // 建立unit类型的netlink的sock
        if (__netlink_create(&init_net, sock, cb_mutex, unit) < 0)
                goto out_sock_release_nosk;

    //第一个参数net,在这里使用
        sk = sock->sk;
        sk_change_net(sk, net);
   
    // 小于32的组号都设置为32
    // ip_queue中该参数为0, nfnetlink中该参数为NFNLGRP_MAX,都不超过32
    // 所以实际两者等价
        if (groups < 32)
                groups = 32;

    // 监听者
        listeners = kzalloc(NLGRPSZ(groups), GFP_KERNEL);
        if (!listeners)
                goto out_sock_release;

        sk->sk_data_ready = netlink_data_ready;
    // netlink接口输入函数,也就是处理用户空间发送到内核方向的数据
        if (input)
                nlk_sk(sk)->netlink_rcv = input;

    // 将该sock插入HASH表,这里和net参数有关,在没有net参数的内核版本中的命令是if (netlink_insert(sk, 0))
        if (netlink_insert(sk, net, 0))
                goto out_sock_release;

    // 设置该netlink sock的一些基本参数
        nlk = nlk_sk(sk);
        nlk->flags |= NETLINK_KERNEL_SOCKET;

        netlink_table_grab();
        if (!nl_table[unit].registered) {
                nl_table[unit].groups = groups;
                nl_table[unit].listeners = listeners;
        //最新的两个参数cb_mutex和module在这里使用
                nl_table[unit].cb_mutex = cb_mutex;
                nl_table[unit].module = module;
                nl_table[unit].registered = 1;
        } else {
                kfree(listeners);
                nl_table[unit].registered++;
        }
        netlink_table_ungrab();
        return sk;

out_sock_release:
        kfree(listeners);
        netlink_kernel_release(sk);
        return NULL;

out_sock_release_nosk:
        sock_release(sock);
        return NULL;
}

 

 

2、解决 rmmod出错的问题

卸载出错后的stack信息如下:

-----------[ cut here ]------------
kernel BUG at mm/slub.c:2743!
invalid opcode: 0000 [#1] SMP
last sysfs file: /sys/devices/pci0000:00/0000:00:1c.1/0000:3f:00.0/irq
Dumping ftrace buffer:
   (ftrace buffer empty)
Modules linked in: nltimer_k(-) ppp_async crc_ccitt arc4 ecb ppp_mppe ppp_generic slhc vfat fat fuse radeon drm ipt_MASQUERADE iptable_nat nf_nat bridge stp bnep sco l2cap bluetooth sunrpc ipv6 cpufreq_ondemand acpi_cpufreq dm_multipath uinput snd_hda_intel snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_alloc snd_hwdep snd tg3 iTCO_wdt ppdev iTCO_vendor_support r8169 parport_pc libphy parport mii soundcore pcspkr serio_raw floppy wmi ata_generic pata_acpi [last unloaded: microcode]

Pid: 4192, comm: rmmod Not tainted (2.6.28 #1) HP Compaq dc7608 Convertible Minitower
EIP: 0060:[<c04907a0>] EFLAGS: 00210246 CPU: 0
EIP is at kfree+0x33/0xd9
EAX: 00000000 EBX: c16febe0 ECX: 00000007 EDX: 00000007
ESI: f7f5fd84 EDI: cbd34f58 EBP: cbd34f48 ESP: cbd34f34
 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process rmmod (pid: 4192, ti=cbd34000 task=e4080cc0 task.ti=cbd34000)
Stack:
 cbd34f3c c042eaf2 00000000 f7f5ec00 cbd34f58 cbd34f50 f7f5e01f cbd34fb0
 c044dee9 69746c6e 5f72656d cbd3006b c04806ed cbc81f78 cbcdf200 cbd34fa0
 f3726360 f3726000 cbd34f88 c049a27e 00000000 00000000 f3726000 00d34fb4
Call Trace:
 [<c042eaf2>] ? put_online_cpus+0x42/0x44
 [<f7f5e01f>] ? nltimer_exit+0xd/0x6a [nltimer_k]
 [<c044dee9>] ? sys_delete_module+0x1ae/0x1f8
 [<c04806ed>] ? remove_vma+0x55/0x5b
 [<c049a27e>] ? path_put+0x15/0x18
 [<c04039bb>] ? sysenter_do_call+0x12/0x34
Code: 83 ec 08 83 f8 10 0f 86 bd 00 00 00 e8 05 dd ff ff 89 c2 89 c3 b8 07 00 00 00 e8 dc dc ff ff 85 c0 75 18 f7 03 00 60 00 00 75 04 <0f> 0b eb fe 89 d8 e8 42 62 fe ff e9 8e 00 00 00 8b 45 04 89 45
EIP: [<c04907a0>] kfree+0x33/0xd9 SS:ESP 0068:cbd34f34
---[ end trace d95ab8b25dc766c7 ]---

 

Google了一下,猜测是kfree()函数的问题,于是将例子中的kfree()都屏蔽掉,于是卸载就没有问题了

你可能感兴趣的:(socket,struct,Module,table,input,insert)