当前位置: 首页 > news >正文

Linux中网络初始化函数sock_init的实现

网络套接字初始化sock_init

void __init sock_init(void)
{int i;/**	Initialize all address (protocol) families. */for (i = 0; i < NPROTO; i++) net_families[i] = NULL;/**	Initialize sock SLAB cache.*/sk_init();#ifdef SLAB_SKB/**	Initialize skbuff SLAB cache */skb_init();
#endif/**	Initialize the protocols module. */init_inodecache();register_filesystem(&sock_fs_type);sock_mnt = kern_mount(&sock_fs_type);/* The real protocol initialization is performed when*  do_initcalls is run.  */#ifdef CONFIG_NETFILTERnetfilter_init();
#endif
}

函数功能概述

sock_init 函数是Linux网络子系统的核心初始化函数,负责建立套接字基础设施

void __init sock_init(void)
{int i;

函数声明:

  • void __init: 初始化函数,完成后内存可被释放
  • sock_init(void): 网络套接字初始化主函数
  • int i: 循环计数器,用于初始化协议家族数组

协议家族数组初始化

	/**	Initialize all address (protocol) families. */for (i = 0; i < NPROTO; i++) net_families[i] = NULL;

协议家族表初始化:

  • 初始化所有地址(协议)家族
  • for (i = 0; i < NPROTO; i++): 遍历所有可能的协议家族
  • net_families[i] = NULL: 将每个协议家族指针初始化为NULL
  • NPROTO: 最大协议数量常量
  • net_families: 全局数组,存储所有注册的网络协议家族处理程序

套接字SLAB缓存初始化

	/**	Initialize sock SLAB cache.*/sk_init();

套接字对象缓存初始化:

  • 初始化sock SLAB缓存
  • sk_init(): 初始化套接字对象的SLAB分配器
  • SLAB缓存: Linux内核的高效内存分配机制
  • 作用: 为struct sock结构体提供快速的内存分配和释放

SKB缓冲区的SLAB缓存初始化

#ifdef SLAB_SKB/**	Initialize skbuff SLAB cache */skb_init();
#endif

条件编译的SKB缓存初始化:

  • #ifdef SLAB_SKB: 只在配置了SLAB_SKB时编译
  • 初始化skbuff SLAB缓存
  • skb_init(): 初始化套接字缓冲区(sk_buff)的SLAB分配器
  • sk_buff: 网络数据包在内核中的表示结构
  • 重要性: sk_buff是网络栈中最频繁分配和释放的数据结构

套接字文件系统初始化

	/**	Initialize the protocols module. */init_inodecache();register_filesystem(&sock_fs_type);sock_mnt = kern_mount(&sock_fs_type);

套接字文件系统设置:

  1. init_inodecache(): 初始化套接字文件系统的efs_inode_info结构体的slab缓存

    • sockfs创建专用的SLAB缓存
    • 提高inode分配效率
  2. register_filesystem(&sock_fs_type): 注册套接字文件系统类型

    • sock_fs_type: 套接字文件系统类型结构体
    • 向VFS注册新的文件系统类型
  3. sock_mnt = kern_mount(&sock_fs_type): 内核挂载套接字文件系统

    • 创建并挂载sockfs的挂载点
    • sock_mnt: 全局变量存储挂载信息

初始化调用说明

	/* The real protocol initialization is performed when*  do_initcalls is run.  */

协议初始化时机说明:

  • 真正的协议初始化在do_initcalls运行时执行
  • 这里只建立基础设施

网络过滤器初始化

#ifdef CONFIG_NETFILTERnetfilter_init();
#endif
}

Netfilter初始化:

  • #ifdef CONFIG_NETFILTER: 只在配置了Netfilter时编译
  • netfilter_init(): 初始化网络过滤框架
  • Netfilter: Linux的包过滤框架,iptables的基础
  • 函数结束

sock初始化sk_init

void __init sk_init(void)
{sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0,SLAB_HWCACHE_ALIGN, NULL, NULL);if (!sk_cachep)printk(KERN_CRIT "sk_init: Cannot create sock SLAB cache!");if (num_physpages <= 4096) {sysctl_wmem_max = 32767;sysctl_rmem_max = 32767;sysctl_wmem_default = 32767;sysctl_rmem_default = 32767;} else if (num_physpages >= 131072) {sysctl_wmem_max = 131071;sysctl_rmem_max = 131071;}
}

函数功能概述

这是一个socket子系统的初始化函数,主要完成两个任务:创建socket对象的内存缓存池,以及根据系统内存大小设置socket缓冲区的大小限制

代码逐段解析

函数定义

void __init sk_init(void)
{
  • void __init: 返回值为void,__init宏表示该函数在系统初始化后会被释放(节省内存)
  • sk_init: 函数名,socket initialize的缩写

创建socket对象缓存池

	sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0,SLAB_HWCACHE_ALIGN, NULL, NULL);
  • sk_cachep: 全局变量,指向socket对象的内存缓存池
  • kmem_cache_create(): 内核内存缓存创建函数,参数如下:
    • "sock": 缓存名称,用于调试和/proc/slabinfo显示
    • sizeof(struct sock): 每个对象的大小,即struct sock结构体的大小
    • 0: 对齐偏移量,0表示使用默认值
    • SLAB_HWCACHE_ALIGN: 标志位,要求硬件缓存行对齐,提高缓存性能
    • NULL: 构造函数指针,这里为NULL表示不需要特殊的初始化
    • NULL: 析构函数指针,这里为NULL表示不需要特殊的清理
	if (!sk_cachep)printk(KERN_CRIT "sk_init: Cannot create sock SLAB cache!");
  • if (!sk_cachep): 检查缓存池是否创建成功
  • printk(KERN_CRIT ...): 如果创建失败,输出关键错误信息到内核日志
  • KERN_CRIT: 表示关键错误级别,通常会在控制台显示

根据系统内存设置socket缓冲区限制

	if (num_physpages <= 4096) {sysctl_wmem_max = 32767;sysctl_rmem_max = 32767;sysctl_wmem_default = 32767;sysctl_rmem_default = 32767;

小内存系统配置(≤4096页):

  • num_physpages <= 4096: 判断物理内存页数是否小于等于4096页
    • 假设页大小为4KB,则4096页 = 16MB内存
  • sysctl_wmem_max = 32767: 设置发送缓冲区最大值为32767字节(约32KB)
  • sysctl_rmem_max = 32767: 设置接收缓冲区最大值为32767字节
  • sysctl_wmem_default = 32767: 设置发送缓冲区默认值为32767字节
  • sysctl_rmem_default = 32767: 设置接收缓冲区默认值为32767字节
	} else if (num_physpages >= 131072) {sysctl_wmem_max = 131071;sysctl_rmem_max = 131071;}
}

大内存系统配置(≥131072页):

  • num_physpages >= 131072: 判断物理内存页数是否大于等于131072页
    • 131072页 = 512MB内存(131072 × 4KB)
  • sysctl_wmem_max = 131071: 设置发送缓冲区最大值为131071字节(约128KB)
  • sysctl_rmem_max = 131071: 设置接收缓冲区最大值为131071字节

详细功能说明

1. 内存缓存池创建

  • 目的: 高效管理socket对象的内存分配
  • 优势:
    • 避免频繁的kmalloc/kfree操作
    • 减少内存碎片
    • 硬件缓存对齐提高性能
  • 重要性: 如果创建失败,整个socket子系统将无法正常工作

2. 缓冲区大小调优

  • 设计理念: 根据系统内存容量自适应调整
  • 三个级别:
    • 小内存系统(≤16MB): 保守配置32KB限制,避免内存耗尽
    • 中等内存系统: 使用内核编译时的默认值
    • 大内存系统(≥512MB): 宽松配置128KB限制,提高网络性能

netfilter初始化netfilter_init

void __init netfilter_init(void)
{int i, h;for (i = 0; i < NPROTO; i++) {for (h = 0; h < NF_MAX_HOOKS; h++)INIT_LIST_HEAD(&nf_hooks[i][h]);}
}

函数功能概述

这是一个netfilter子系统的初始化函数,用于初始化网络协议钩子(hook)的双向链表结构,为后续的网络包过滤、NAT等功能的钩子函数注册做好准备

代码逐段解析

函数定义

void __init netfilter_init(void)
{
  • void __init: 返回值为void,__init宏表示该函数在系统初始化后会被释放(节省内存)
  • netfilter_init: 函数名,netfilter initialize的缩写

变量声明

	int i, h;
  • int i: 外层循环计数器,用于遍历网络协议
  • int h: 内层循环计数器,用于遍历钩子点

嵌套循环初始化

	for (i = 0; i < NPROTO; i++) {for (h = 0; h < NF_MAX_HOOKS; h++)INIT_LIST_HEAD(&nf_hooks[i][h]);}
}
外层循环
for (i = 0; i < NPROTO; i++)
  • i = 0: 从第一个协议开始
  • i < NPROTO: 循环条件,NPROTO是网络协议的数量常量
  • 遍历所有支持的网络协议(如IPv4、IPv6、ARP等)
内层循环
for (h = 0; h < NF_MAX_HOOKS; h++)
  • h = 0: 从第一个钩子点开始
  • h < NF_MAX_HOOKS: 循环条件,NF_MAX_HOOKS是每个协议支持的最大钩子点数
  • 遍历每个协议的所有可能钩子点
链表头初始化
INIT_LIST_HEAD(&nf_hooks[i][h]);
  • INIT_LIST_HEAD(): Linux内核双向链表初始化宏
  • &nf_hooks[i][h]: 取第i个协议第h个钩子点的链表头地址
  • nf_hooks: 全局的二维数组,结构为:struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]

数据结构详细说明

nf_hooks二维数组结构

nf_hooks[NPROTO][NF_MAX_HOOKS]
│
├── [0] (IPv4协议)
│   ├── [0] NF_IP_PRE_ROUTING  钩子链表
│   ├── [1] NF_IP_LOCAL_IN     钩子链表  
│   ├── [2] NF_IP_FORWARD      钩子链表
│   ├── [3] NF_IP_LOCAL_OUT    钩子链表
│   └── [4] NF_IP_POST_ROUTING 钩子链表
│
├── [1] (IPv6协议)
│   ├── [0] NF_IP6_PRE_ROUTING 钩子链表
│   └── ...
│
├── [2] (ARP协议)
│   └── ...
│
└── ... (其他协议)

INIT_LIST_HEAD宏的作用

#define INIT_LIST_HEAD(ptr) do { \(ptr)->next = (ptr); \(ptr)->prev = (ptr); \
} while (0)
  • 将链表头的nextprev指针都指向自己
  • 创建一个空的双向循环链表
http://www.dtcms.com/a/525487.html

相关文章:

  • 数据结构——KMP算法
  • 湖北微网站建设报价我的手机网站
  • Spring集成WebSocket
  • MinerU系列最新迭代版本上线,专为高精度、高效率的文档解析任务设计;清华、字节联合推出HuMo,实现三模态协同生成人物视频
  • 什么是企业营销型网站seo公司优化排名
  • 洛阳有做网站开发的吗wordpress重构
  • 呼和浩特网站建设电话西安网页设计培训
  • uniapp开发小程序,实现开通会员卡页面
  • 微信小程序开发案例 | 简易登录小程序
  • uniapp开发小程序,Canvas实现海报生成邀请码,邀请好友功能
  • 江苏省建设斤网站宁波seo关键词
  • 第 03 天:Linux 文件夹结构与文件类型
  • 网站页面安全监测建设方案成为软件工程师的条件
  • cesium点、线、面、模型
  • 风电项目管理软件:陆上风电、海上风电、山地风电、戈壁风电、风电吊装、风电EPC、风电安装与施工等建设工程的信息与数字化管理
  • 深圳公司建立网站电子商务网站应该如何建设
  • 建设厅网站实名制系统如何解聘租个网站服务器多少钱
  • 天硕工业级固态硬盘:以主动抗浪涌技术定义高可靠国产存储标杆
  • Linux文件系统挂载与卸载完全指南
  • 测试:uk8s创建监控和告警同步飞书等渠道
  • 欧美做暖网站哈尔滨网站建设效果好
  • 南开大学 网站开发技术 刘冲关于行业网站建设意见
  • React学习笔记(一)
  • Linux综合练习
  • 与网站开发相关的书籍国家免费职业培训平台
  • 机器人外呼人机耦合还有哪些潜在成本误区
  • 详细讲解条件变量
  • 筑牢风控生命线:金仓数据库替代MongoDB,重构证券融资融券业务的数据基石
  • 网站的时间对齐应该怎么做ftp跟网络连接Wordpress
  • 阿里云国际站GPU:怎么通过控制台自助排查功能诊断GPU?