声明:本文为原创
#####请转贴时保留以下内容######
作者:GTT
请提出宝贵意见Mail:mtloveft@hotmail.com 
Linux Version:2.6.33
提示:本文是介绍linux 网络协议栈初始化!
  
 
网络命名空间的初始化是linux网络协议栈中第一个被初始化的。为什么要先初始化网络命名空间呢。
因为旧版本的关于网络的全局变量都被包含到命名空间了。所以必须先初始化网络命名空间。
根据以下代码
pure_initcall(net_ns_init); //net/core/net_namespace.c
就知道net_ns_init是被先执行的。
 
它的代码如下
| static int __init net_ns_init(void){
 struct net_generic *ng;
 
 #ifdef CONFIG_NET_NS
 net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
 SMP_CACHE_BYTES, SLAB_PANIC, NULL);
 
 /* Create workqueue for cleanup */
 netns_wq = create_singlethread_workqueue("netns");
 if (!netns_wq) panic("Could not create netns workq");
 #endif
 
 ng = net_alloc_generic();
 if (!ng) panic("Could not allocate generic netns");
 
 rcu_assign_pointer(init_net.gen, ng);
 
 mutex_lock(&net_mutex);
 if (setup_net(&init_net))
 panic("Could not setup the initial network namespace");
 
 rtnl_lock();
 list_add_tail_rcu(&init_net.list, &net_namespace_list);
 rtnl_unlock();
 
 mutex_unlock(&net_mutex);
 
 return 0;
 }
 | 
 
 
编译内核时如果没指定CONFIG_NET_NS这项
CONFIG_NET_NS是编译配置选项,用户可以重构网络空间结构。
也就是struct net结构。Kernel主要是考虑扩展性和灵活性。
一般用户不会配置此项,kernel提供一个默认的值即init_net
在net_ns_init方法里对init_net进行初始化。
init_net的定义如下
struct net init_net;
 
网络命名空间定义了2个链表,pernet_list和net_namespace_list
如下
static LIST_HEAD(pernet_list);
static struct list_head *first_device = &pernet_list;
LIST_HEAD(net_namespace_list);
init_net会被链接到net_namespace_list这个双向链表上。
pernet_operations结构将被链接到pernet_list这个双向链表上。
以后,如果没自定义网络命名空间的话,所有想用网络命名空间时都将利用init_net。
 
 
 
| /** setup_net runs the initializers for the network namespace object.
 */
 static __net_init int setup_net(struct net *net)
 {
 /* Must be called with net_mutex held */
 const struct pernet_operations *ops, *saved_ops;
 int error = 0;
 LIST_HEAD(net_exit_list);
 
 atomic_set(&net->count, 1);
 
 #ifdef NETNS_REFCNT_DEBUG
 atomic_set(&net->use_count, 0);
 #endif
 
 list_for_each_entry(ops, &pernet_list, list) {
 error = ops_init(ops, net);
 if (error < 0) goto out_undo;
 }
 out:
 return error;
 
 out_undo:
 /* Walk through the list backwards calling the exit functions
 * for the pernet modules whose init functions did not fail.
 */
 list_add(&net->exit_list, &net_exit_list);
 saved_ops = ops;
 list_for_each_entry_continue_reverse(ops, &pernet_list, list)
 ops_exit_list(ops, &net_exit_list);
 
 ops = saved_ops;
 list_for_each_entry_continue_reverse(ops, &pernet_list, list)
 ops_free_list(ops, &net_exit_list);
 
 rcu_barrier();
 goto out;
 }
 |