linux内核必须用c而非c++,因内核剥离了c++运行时(异常、rtti、构造/析构、标准库),new/delete未定义,abi不兼容,且所有api声明为extern "c";包过滤应基于netfilter框架用c实现。

不能直接用 C++ 指针在内核空间实现包过滤防火墙——Linux 内核不支持 C++ 运行时,也不允许用户态 C++ 代码直接运行在内核态。
为什么内核模块必须用 C 而不是 C++
内核编译环境剥离了 libstdc++、异常处理、RTTI、构造/析构自动调用等机制;new/delete 操作符未定义;std::vector、std::string 等容器无法链接。即使强制用 g++ -x c++ 编译,链接阶段会报 undefined reference to `__cxa_begin_catch' 类错误。
- 内核头文件(如
<linux></linux>)只适配 C ABI -
struct sk_buff *等核心数据结构的字段访问依赖 C 的内存布局,C++ 的访问控制或虚函数表会破坏兼容性 - 所有内核 API(如
nf_register_net_hook)声明为extern "C"风格,C++ 名字修饰会导致符号找不到
包过滤真正该用的接口是 netfilter + C
实际做法是写一个 C 语言内核模块,注册 nf_hook_ops 结构体到 IPv4 的 NF_INET_PRE_ROUTING 或 NF_INET_LOCAL_OUT 链,然后在回调函数中用原始指针操作 struct sk_buff * 解析 IP/TCP 头。
- 不要自己解析二进制包:用
skb_network_header()和ip_hdr()获取 IP 头指针,再用tcp_hdr()(需先确认协议和 offset) - 判断方向时注意:
skb->pkt_type == PACKET_HOST表示发给本机,PACKET_OUTGOING是本机发出 - 丢弃包用
return NF_DROP,放行用return NF_ACCEPT;别直接kfree_skb()—— netfilter 框架会管理生命周期
static unsigned int filter_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state) {
struct iphdr *iph = ip_hdr(skb);
if (iph->protocol == IPPROTO_TCP) {
struct tcphdr *tcph = tcp_hdr(skb);
if (ntohs(tcph->dest) == 22) // 拦截 SSH
return NF_DROP;
}
return NF_ACCEPT;
}
指针操作中最容易崩的三个地方
看似只是解引用指针,但在内核上下文中,任何假设都可能触发 oops:
-
skb->data可能未对齐或被分段(skb_is_nonlinear()为真),直接强转struct iphdr *会读越界 → 必须先skb_network_header() - IP 头长度不固定(
iph->ihl * 4),TCP 头起始位置不是iph + 1,要用iph->ihl * 4偏移计算 - SKB 可能被 GSO/GRO 合并,
tcp_hdr()在非线性 SKB 上可能返回无效地址 → 应先skb_linearize(skb)(代价高,慎用)或改用skb_header_pointer()
真正动手时,90% 的 panic 来自指针偏移没校验、协议字段没判空、或忘了 skb_pull() 后重新获取头指针。内核没有 segfault,只有静默数据损坏或立即 panic。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











