3. Linux内核协议栈裁剪基础:内核配置系统(Kconfig/Makefile)、裁剪网络子系统、移除不必要的协议族

各位同学,今天咱们聊点实在的。内核协议栈裁剪,说白了就是给网络协议栈“瘦身”。我刚开始做嵌入式系统移植那会儿,总觉得内核越大越全越好,结果产品一跑起来,内存吃紧,延迟还高。后来才明白——你不需要的东西,就是负担

这一节,我带你从内核的配置系统入手,一步步把网络子系统里那些用不上的东西砍掉。嗯,咱们的目标很明确:让协议栈跑得更快,占得更少

3.1 内核配置系统:Kconfig与Makefile的默契配合

内核的裁剪,核心就是靠Kconfig和Makefile这两兄弟。Kconfig负责“问你要不要”,Makefile负责“你要就编译”。

Kconfig的语法其实不复杂。我举个例子,你一看就懂:

config NET_VENDOR_INTEL
    bool "Intel devices"
    default y
    help
      If you have a network (Ethernet) card belonging to this class, say Y.

这里bool表示开关选项,default y就是默认开启。我个人习惯,在裁剪时会把所有不用的vendor驱动都设成default n,省得编译时还得手动一个个关。

Makefile那边就更直接了:

obj-$(CONFIG_NET_VENDOR_INTEL) += intel/

看到没?CONFIG_NET_VENDOR_INTEL如果被选为y,就编译intel目录下的驱动。如果是m,就编译成模块。如果是空的,那就跳过。

小技巧: 我建议你在裁剪前,先用make menuconfig生成一个.config文件,然后备份。这样万一裁坏了,还能快速恢复。

3.2 裁剪网络子系统:从宏观到微观

网络子系统是内核里最庞大的模块之一。你想想看,从网卡驱动到协议栈,再到socket接口,层层叠叠。裁剪它,得有个顺序。

我个人习惯分三步走:

  1. 关掉不用的网卡驱动 —— 嵌入式设备通常只有一两种网卡,其他全砍掉。
  2. 关掉不用的网络功能 —— 比如桥接、VLAN、多播路由,用不上就关。
  3. 关掉不用的协议族 —— 这个咱们下一节细说。

具体操作时,你可以在make menuconfig里进入Networking support -> Networking options。这里面的选项密密麻麻,我挑几个常见的说说:

配置项 说明 裁剪建议
CONFIG_PACKET 原始套接字支持 如果不用tcpdump,可以关掉
CONFIG_NETFILTER 网络过滤框架 嵌入式设备通常不需要防火墙,关掉
CONFIG_BRIDGE 网桥支持 只有做交换机才需要
CONFIG_IP_MULTICAST IP多播 大部分场景用不上

我曾经在一个项目里,把CONFIG_NETFILTER关掉后,网络吞吐量提升了将近15%。为什么?因为数据包不再经过那些hook点了,路径短了,自然就快了。

注意: 裁剪前一定要确认你的应用层依赖。比如你关了CONFIG_PACKET,那libpcap就用不了了。我吃过这个亏,调试时抓不了包,急得满头大汗。

3.3 移除不必要的协议族

协议族,就是AF_INETAF_INET6AF_NETLINK这些。内核里支持的协议族很多,但你的设备可能只用其中一两个。

我见过有些嵌入式设备,明明只用IPv4,却把IPv6、DECnet、IPX这些全编译进去了。这不是浪费吗?

裁剪协议族,主要是在Networking support -> Networking options里操作。我列几个常见的:

  • IPv6:如果设备只跑IPv4,直接关掉CONFIG_IPV6。能省下不少内存和CPU开销。
  • DECnet:这是老古董了,现在基本没人用。关掉。
  • IPX:Novell时代的协议,关掉。
  • NETLINK:这个要小心。很多内核工具(比如ip命令)依赖它。如果不用这些工具,可以关掉。

嗯,这里要注意:协议族的裁剪,影响的不只是内核大小,还有运行时的性能。因为每个协议族在初始化时都会注册自己的处理函数,增加协议栈的查找开销。

我举个例子。假设你的设备只跑IPv4,那你可以把CONFIG_INET保留,其他全关。这样内核在收到数据包时,只需要匹配IPv4的协议号,不用去遍历其他协议族的处理函数。路径短了,延迟自然就低了。

核心思路: 裁剪不是目的,目的是让协议栈更专注。你砍掉的东西越多,剩下的路径就越短,延迟就越低。

3.4 实战:用SVG画一张裁剪流程图

说了这么多,咱们用一张图来总结一下裁剪的流程。我画了个SVG,你一看就明白:

内核协议栈裁剪流程图 1. 备份原始.config 2. 裁剪网卡驱动 3. 裁剪网络功能 4. 移除协议族 5. 编译测试 裁剪要点 • 网卡驱动:只保留设备实际使用的 • 网络功能:桥接、VLAN、多播等按需保留 • 协议族:IPv4保留,IPv6/DECnet/IPX移除 • 每次裁剪后都要编译测试,避免功能缺失

这张图把裁剪流程串起来了。你照着这个顺序做,基本不会出大问题。

3.5 避坑指南

最后,我分享几个实战中踩过的坑:

  • 别一次裁太多 —— 我刚开始时,恨不得把所有不认识的选项全关掉。结果编译出来,网络根本起不来。后来学乖了,每次只关几个选项,然后编译测试。
  • 注意依赖关系 —— 有些选项之间有依赖。比如你关了CONFIG_INET,那所有依赖IPv4的功能都会失效。内核在make menuconfig里会提示,但有时候提示不明显,你得仔细看。
  • 保留调试接口 —— 我建议至少保留CONFIG_NET_SCHEDCONFIG_NET_CLS,方便后期做QoS调试。当然,如果产品已经稳定了,可以再关掉。

好了,这一节的内容就到这儿。裁剪协议栈是个细致活,急不得。你按照我上面说的步骤来,一步步裁,一步步测,很快就能上手。

记住:少即是多。你砍掉的每一行代码,都可能让协议栈跑得更快。

专注资料整理