Linux内核-协议栈-初始化流程分析

本文主要针对Linux-3.19.3版本的内核简单分析内核协议栈初始化涉及到的主要步骤和关键函数,不针对协议的解析以及数据包的处理流程做具体分析,后续有机会再详细分析


1.准备

  • Linux内核协议栈本身构建在虚拟文件系统之上,所以对Linux VFS不太了解的可以参考内核源码根目录下Documentation/filesystems/vfs.txt,另外,socket接口层,协议层,设备层的许多数据结构涉及到内存管理,所以对基本虚拟内存管理,slab缓存,页高速缓存不太了解的也可以查阅相关文档。

  • 源码涉及的主要文件位于net/socket.c,net/core,include/linux/net*. 基本上整个初始化过程主要与net,net_namespace,/proc,/proc/sys相关结构的初始化和文件的建立,主要使用register_pernet_subsystem钩子注册和调用各种操作.init和.exit


2.开始

开始分析前,这里有些小技巧可以快速定位到主要的初始化函数,在分析其他子系统源码时也可以采用这个技巧

grep _initcall socket.c
find ./core/ -name "*.c" |xargs cat | grep _initcall
grep net_inuse_init tags

这里写图片描述
这里写图片描述

这里*__initcall宏是设置初始化函数位于内核代码段.initcall#id.init的位置其中id代表优先级level,小的一般初始化靠前,定义在include/linux/init.h,使用gcc的attribute扩展。而各个level的初始化函数的调用流程基本如下:

start_kernel -> rest_init -> kernel_init内核线程 -> kernel_init_freeable -> do_basic_setup -> do_initcalls -> do_initcall_level -> do_one_initcall -> *(initcall_t)

这里写图片描述


3.详细分析

  • 可以看到pure_initcall(net_ns_init)位于0的初始化level,基本不依赖其他的初始化子系统,所以从这个开始
//core/net_namespace.c
//基本上这个函数主要的作用是初始化net结构init_net的一些数据,比如namespace相关,并且调用注册的pernet operations的init钩子针对net进行各自需求的初始化
pure_initcall(net_ns_init);
static int __init net_ns_init(void)
{
    struct net_generic *ng;
    //net namespace相关
#ifdef CONFIG_NET_NS
    //分配slab缓存
    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);
    //初始化net namespace相关的对象, 传入初始的namespace init_user_ns
    //设置net结构的初始namespace
    //对每个pernet_list中注册的pernet operation&#

你可能感兴趣的:(系统,linux,kernel,协议栈)