Chinaunix首页 | 论坛 | 博客
  • 博客访问: 629844
  • 博文数量: 155
  • 博客积分: 5688
  • 博客等级: 大校
  • 技术积分: 2134
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-15 15:12
文章分类

全部博文(155)

文章存档

2011年(58)

2010年(97)

分类: LINUX

2010-09-18 15:49:10

声明:本文为原创
#####请转贴时保留以下内容######
作者GTT
本文档归属http://oldtown.cublog.cn/.转载请注明出处!
请提出宝贵意见Mail:mtloveft@hotmail.com
Linux Version:2.6.33
提示本文是介绍linux 网络协议栈初始化
 
core_initcall级别的网络初始化方法还有net_inuse_init
首先看看它的source code,然后分析这个网络初始化方法都干了些什么。

static __init int net_inuse_init(void)
{
    if (register_pernet_subsys(&net_inuse_ops))
        panic("Cannot initialize net inuse counters");

    return 0;
}

register_pernet_subsys方法在一个网络命名空间里注册子系统。
 
注册net_inuse_ops,它的定义如下

static struct pernet_operations net_inuse_ops = {
    .init = sock_inuse_init_net,
    .exit = sock_inuse_exit_net,
}

 
我们再看看register_pernet_subsys是如何注册这个op的。
它的代码如下

int register_pernet_subsys(struct pernet_operations *ops)
{
    int error;
    mutex_lock(&net_mutex);
    error = register_pernet_operations(first_device, ops);
    mutex_unlock(&net_mutex);
    return error;
}

 
继续跟进register_pernet_operations
这个first_device linux网络协议栈初始化Series---(2) 介绍网络命名初始化里介绍过。
看看它的source code

static int register_pernet_operations(struct list_head *list, struct pernet_operations *ops)
{
    int error;

    if (ops->id) {
again:
        error = ida_get_new_above(&net_generic_ids, 1, ops->id);
        if (error < 0) {
            if (error == -EAGAIN) {
                ida_pre_get(&net_generic_ids, GFP_KERNEL);
                goto again;
            }
            return error;
        }
    }
    error = __register_pernet_operations(list, ops);
    if (error) {
        rcu_barrier();
        if (ops->id) ida_remove(&net_generic_ids, *ops->id);
    }

    return error;
}

 
如果ops设定了id,那么分配新的ID,然后执行__register_pernet_operations看看它的source code

static int __register_pernet_operations(struct list_head *list,
                    struct pernet_operations *ops)
{
    int err = 0;
    err = ops_init(ops, &init_net);
    if (err) ops_free(ops, &init_net);
    return err;

}

在这个方法里调用,这又回到了linux网络协议栈初始化Series---(2) 里初始化网络命名空间里一样的方法。
再稍微介绍一下,初始化网络命名空间方法ops_init的source 如下

static int ops_init(const struct pernet_operations *ops, struct net *net)
{
    int err;
    if (ops->id && ops->size) {
        void *data = kzalloc(ops->size, GFP_KERNEL);
        if (!data) return -ENOMEM;

        err = net_assign_generic(net, *ops->id, data);
        if (err) {
            kfree(data);
            return err;
        }
    }
    if (ops->init)
        return ops->init(net);
    return 0;
}

如果设定了ops的id和size,那么从内核堆内存里申请size大小的内存。重新设定net。
然后调用ops设定的init方法。
其实在新的网络命名空间里,之前设定的ops,将都被重新设定一遍。也就是子网络命名空间,继承了
父网络命名空间的内容。
 
 
 
 
 
 
 






阅读(1842) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-21 08:14:56

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com