本文主要针对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,调用其初始化net中的对应数据对象
if (setup_net(&init_net, &init_user_ns))

本文分析了Linux-3.19.3内核协议栈的初始化过程,包括主要步骤和关键函数,如net_namespace、/proc和/proc/sys的初始化。重点介绍了纯初始化函数net_ns_init,接着是sock_init,涉及net_inuse_init、netpoll_init、proto_init、net_dev_init及sysctl_core_init等。虽然初始化过程简单,但完整的数据包处理流程将在后续分析中探讨。
最低0.47元/天 解锁文章
7830

被折叠的 条评论
为什么被折叠?



