struct sk_buff详解

sk_buff数据结构详解 sk_buff 简介 封包存储于struct sk_buff中,所有网络分层都会使用这个结构来储存其报头、有关用户数据的信息,以及协调其工作的其他内部信息。从第二层到第四层都会使用这个数据结构。L4附加一个报头传给L3,L3附加自己的报头传给L2,L2附加自己的报头传给L1转发出去。设备收到sk_buff之后,每层都只处理自己的报头,并将其呈交给上层。 sk_buff数据结构 内核使用一个双向链表来维护sk_buff,链表的开端使用了一个哑元元素sk_buff_head,如下图所示为sk_buff链表 阅读详情

sk_buff是Linux网络代码中最重要的结构体之一。它是Linux在其协议栈里传送的结构体,也就是所谓的“包”,在他里面包含了各层协议的头部,比如ethernet, ip ,tcp ,udp等等。也有相关的操作等。熟悉他是进一步了解Linux网络协议栈的基础。

struct sk_buff {
	/* These two members must be first. */
	struct sk_buff	*next;
	struct sk_buff	*prev;

	struct sock  *sk;
	ktime_t  tstamp;
	struct net_device  *dev;

	unsigned long  _skb_dst;
#ifdef CONFIG_XFRM
	struct	sec_path  *sp;
#endif
	/*
	 * This is the control buffer. It is free to use for every
	 * layer. Please put your private variables there. If you
	 * want to keep them across layers you have to do a skb_clone()
	 * first. This is owned by whoever has the skb queued ATM.
	 */
	char	cb[48];

	unsigned int  len,
		      data_len;
	__u16         mac_len,
		      hdr_len;
	union {
		__wsum	csum;
		struct {
			__u16	csum_start;
			__u16	csum_offset;
		};
	};
	__u32		priority;
	kmemcheck_bitfield_begin(flags1);
	__u8	local_df:1,
		cloned:1,
		ip_summed:2,
		nohdr:1,
		nfctinfo:3;
	__u8	pkt_type:3,
		fclone:2,
		ipvs_property:1,
		peeked:1,
		nf_trace:1;
	__be16	protocol:16;
	kmemcheck_bitfield_end(flags1);

	void	(*destructor)(struct sk_buff *skb);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
	struct nf_conntrack	*nfct;
	struct sk_buff	*nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
	struct nf_bridge_info	*nf_bridge;
#endif

	int			iif;
#ifdef CONFIG_NET_SCHED
	__u16			tc_index;	/* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
	__u16			tc_verd;	/* traffic control verdict */
#endif
#endif

	kmemcheck_bitfield_begin(flags2);
	__u16			queue_mapping:16;
#ifdef CONFIG_IPV6_NDISC_NODETYPE
	__u8			ndisc_nodetype:2;
#endif
	kmemcheck_bitfield_end(flags2);

	/* 0/14 bit hole */

#ifdef CONFIG_NET_DMA
	dma_cookie_t		dma_cookie;
#endif
#ifdef CONFIG_NETWORK_SECMARK
	__u32			secmark;
#endif

	__u32			mark;

	__u16			vlan_tci;

	sk_buff_data_t		transport_header;
	sk_buff_data_t		network_header;
	sk_buff_data_t		mac_header;
	/* These elements must be at the end, see alloc_skb() for details.  */
	sk_buff_data_t		tail;
	sk_buff_data_t		end;
	unsigned char		*head,
				*data;
	unsigned int		truesize;
	atomic_t		users;
};

此结构定义在<include/linux/skbuff.h>头文件中,结构体布局大致可分为以下四部分:

l       布局(layout)

l       通用(general)

l       功能专用(feature-specific)

l       管理函数(management functions)

网络选项以及内核结构

      我们可以看到在此结构体里有很多预处理,他是在需要指定相应功能时才起作用,我们在这里先对通用的作出分析。

布局字段:

      sk_buff是一个复杂的双向链表,在他结构中有next和prev指针,分别指向链表的下一个节点和前一个节点。并且为了某些需求(不知道是哪些目前)需要很快定位到链表头部,所以还有一个指向链表头部的指针list(我在2.6.25内核没有发现这个指针)。

sk_buff_head结构是:

struct sk_buff_head {

      /* These two members must be first. */

      struct sk_buff *next;

      struct sk_buff *prev;

      __u32       qlen; //代表元素节点数目

      spinlock_t      lock; //加锁,防止对表的并发访问

};

  

struct sock *sk

这个指针指向一个套接字sock数据结构。当数据在本地产生或者本地进程接受时,需要这个指针;里面的数据会有tcp/udp和用户态程序使用。如果是转发此指针为NULL

unsigned int len

缓冲区中数据块大小。长度包括:主要缓冲区(head所指)的数据以及一些片断(fragment)的数据。当包在协议栈向上或向下走时,其大小会变,因为有头部的丢弃和添加。

unsigned int data_len

片段中数据大小

unsigned int mac_len

mac包头大小

atomic_t users

      引用计数,使用这个sk_buff的使用者的数目,可能有多个函数要使用同一个sk_buff所以防止提前释放掉,设置此计数

unsigned int truesize

      此缓冲区总大小,包括sk_buff。sk_buff只不过是个指针的集合,他所指的才是真正的数据区,所以是两部分。(见下图)

sk_buff_data_t          tail;

sk_buff_data_t          end;

unsigned char      *head, *data;

      这些指针很重要,他们指向的是真正的数据区,他们的边界。head和end指向的是数据区的开端和尾端(注意和data,tail区别)如下图,data和tail指向的是实际数据的开头和结尾。

      因为数据区在协议栈走的时候要一层层添加或去掉一些数据(比如报头)所以申请一块大的足够的内存,然后在往里放东西。真实的实际数据可能用不了这么多,所以用data,tail指向真实的,head,tail指向边界。刚开始没填充数据时前三个指针指向的是一个地方。

 

               

void (*destructor) (…….)

      此函数指针被初始化一个函数,当此缓冲区删除时,完成某些工作。

通用字段

struct timeval stamp(2.6.25没有,估计是ktime_t tstamp)

      时间戳,表示何时被接受或有时表示包预定的传输时间

struct net_device *dev

      描述一个网络设备,我会以后分析他。

sk_buff_data_t          transport_header; //L4

sk_buff_data_t          network_header; //L3

sk_buff_data_t          mac_header; //L2

这些指针分别指向报文头部,和2.4版本比较有了变化,不再是联合体,使用更加方便了,Linux给出了很方便的函数直接定位到各层的头部。下图是2.4版本的,只是说明一下。

 

struct dst_entry dst

      路由子系统使用。目前不知道怎么回事呢。据说比较复杂。

char cb[40]

      缓冲控制区,用来存储私有信息的空间。比如tcp用这个空间存储一个结构体tcp_skb_cb ,可以用宏TCP_SKB_CB(__skb)定位到他,然后使用里面的变量。

ip_summed:2

__wsum   csum;

      校验和

unsigned char pkt_type

      根据L2层帧的目的地址进行类型划分。

unsigned char cloned

      表示该结构是另一个sk_buff克隆的。

__u32            priority;

      QoS等级

__be16                protocol;

      从L2层设备驱动看使用在下一个较高层的协议。

功能专用字段

Linux是模块化的,你编译时可以带上特定功能,比如netfilter等,相应的字段才会生效。应该是那些预定义控制的。

 

管理函数

下面这个图是:(a*)skb_put; (b*) skb_push; (c*) skb_pull (d*) skb_reserve的使用,主要是对skb_buf所指向的数据区的指针移动。(数据预留以及对齐)

 

 

下图是用skb_reserve函数,把一个14字节的ethernet帧拷贝到缓冲区。skb_reserve(skb, 2), 2表示16字节对齐。14+2=16

 

下图是穿过协议栈从tcp层向下到链路层的过程

 

 

分配内存:

alloc_skb 分配缓冲区和一个sk_buff结构

dev_alloc_skb 设备驱动程序使用的缓冲区分配函数

释放内存:

kfree_skb 只有skb->users计数器为1时才释放

dev_kfree_skb

缓冲区克隆函数 skb_clone

 

列表管理函数:

skb_queue_head_init

      队列初始化

skb_queue_head , skb_queue_tail

      把一个缓冲区添加到队列头或尾

skb_dequeue, skb_dequeue_tail

      从头或尾去掉

skb_queue_purge

      把队列变空

skb_queue_walk

      循环队列每个元素

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->内核也新增了几个函数,来提供获取这些偏移的接口:
#ifdef NET_SKBUFF_DATA_USES_OFFSET
如果使用了offset来表示偏移的话,就是说是一个相对偏移的情况:
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
 return skb->head + skb->transport_header;
}
static inline void skb_reset_transport_header(struct sk_buff *skb)
{
 skb->transport_header = skb->data - skb->head;
}
static inline void skb_set_transport_header(struct sk_buff *skb,
         const int offset)
{
 skb_reset_transport_header(skb);
 skb->transport_header += offset;
}
static inline unsigned char *skb_network_header(const struct sk_buff *skb)
{
 return skb->head + skb->network_header;
}
static inline void skb_reset_network_header(struct sk_buff *skb)
{
 skb->network_header = skb->data - skb->head;
}
static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
{
 skb_reset_network_header(skb);
 skb->network_header += offset;
}
static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
{
 return skb->head + skb->mac_header;
}
static inline int skb_mac_header_was_set(const struct sk_buff *skb)
{
 return skb->mac_header != ~0U;
}
static inline void skb_reset_mac_header(struct sk_buff *skb)
{
 skb->mac_header = skb->data - skb->head;
}
static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
{
 skb_reset_mac_header(skb);
 skb->mac_header += offset;
}
#else /* NET_SKBUFF_DATA_USES_OFFSET */
不使用相对偏移的情况
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
 return skb->transport_header;
}
static inline void skb_reset_transport_header(struct sk_buff *skb)
{
 skb->transport_header = skb->data;
}
static inline void skb_set_transport_header(struct sk_buff *skb,
         const int offset)
{
 skb->transport_header = skb->data + offset;
}
static inline unsigned char *skb_network_header(const struct sk_buff *skb)
{
 return skb->network_header;
}
static inline void skb_reset_network_header(struct sk_buff *skb)
{
 skb->network_header = skb->data;
}
static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
{
 skb->network_header = skb->data + offset;
}
static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
{
 return skb->mac_header;
}
static inline int skb_mac_header_was_set(const struct sk_buff *skb)
{
 return skb->mac_header != NULL;
}
static inline void skb_reset_mac_header(struct sk_buff *skb)
{
 skb->mac_header = skb->data;
}
static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
{
 skb->mac_header = skb->data + offset;
}
#endif /* NET_SKBUFF_DATA_USES_OFFSET */

1、TCP层获取相关偏移的函数
static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb)
{
 return (struct tcphdr *)skb_transport_header(skb);
}
这个函数用来获得sk_buff结构中TCP头的指针
static inline unsigned int tcp_hdrlen(const struct sk_buff *skb)
{
 return tcp_hdr(skb)->doff * 4;
}
这个函数用来获得TCP头的长度
static inline unsigned int tcp_optlen(const struct sk_buff *skb)
{
 return (tcp_hdr(skb)->doff - 5) * 4;
}
获取tcp option的长度
2、IP相关的函数
static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
{
 return (struct iphdr *)skb_network_header(skb);
}
该函数获得ip头
static inline struct iphdr *ipip_hdr(const struct sk_buff *skb)
{
 return (struct iphdr *)skb_transport_header(skb);
}
该函数获得ipip头,实际上偏移已经跑到了传输层的开始
3、MAC相关函数
static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb)
{
 return (struct ebt_802_3_hdr *)skb_mac_header(skb);
}
获取802.3MAC头指针。

static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
{
    return (struct ethhdr *)skb_mac_header(skb);
}
获取以太网MAC头指针。以太网头指针结构体: 
struct ethhdr {
    unsigned char    h_dest[ETH_ALEN];    /* destination eth addr    */
    unsigned char    h_source[ETH_ALEN];    /* source ether addr    */
    __be16        h_proto;        /* packet type ID field    */
} __attribute__((packed));

内核中网络地址转化为字符串形式的IP地址的宏定义:
#define NIPQUAD(addr) \ 
((unsigned char *)&addr)[0], \ 
((unsigned char *)&addr)[1], \ 
((unsigned char *)&addr)[2], \ 
((unsigned char *)&addr)[3] 
#define NIPQUAD_FMT "%u.%u.%u.%u"


`sk_buff` 结构体详解(包含全生命周期解析) Linux网络数据包核心结构sk_buff解析与生命周期管理 sk_buff是Linux网络协议栈处理数据包的核心数据结构,包含数据缓冲区、协议信息和设备信息等关键成员。其生命周期分为接收和发送两条路径:接收路径从网卡驱动创建sk_buff开始,经协议栈处理后交付应用层;发送路径则由应用层发起,经协议栈封装后由网卡驱动发送。文中详细解析了sk_buff的内存布局、关键操作函数(如分配/释放、数据操作、分片管理等)以及特殊场景处理(如零拷贝)。最后提供了内存预分配、DMA优化等性能优化技巧。 阅读详情

相关推荐

TCP协议核心机制与Linux内核实现深度解析

TCP协议作为网络传输层的基石,通过序列号、确认应答和重传机制构建可靠数据传输。其核心技术包括三次握手建立连接、滑动窗口流量控制、动态RTO计算等机制,在Linux内核中通过struct sock等数据结构实现。现代拥塞控制算法如CUBIC和BBR通过非线性增长函数实现带宽高效利用,而TCP Fast Open等技术进一步优化网络延迟。在5G和容器化环境下,协议栈面临毫米波波动、网络切片等新挑战,需要结合sysctl调优和SO_REUSEPORT等特性实现高性能网络通信。

weixin_28323057的博客 284

struct sk_buff结构体详解

struct sk_buff是linux网络系统中的核心结构体,linux网络中的所有数据包的封装以及解封装都是在这个结构体的基础上进行。structsk_buff_head { structsk_buff*next; structsk_buff*prev; __u32qlen; spinlock_tlock;...

weixin_33906657的博客 952

第四章 内核数据转发sk_buff结构说明

编写内核数据转发代码之前需要对内核报文的数据结构以及函数说明有详细的了解,才能在后续的编码中能够根据自己的需求进行快速的开发。

flowhehe的博客 802

sk_buff结构分析

前言: 以下是根据《深入理解Linux网络技术内幕》对sk_buff的相关总结,由于是刚刚看这本书(太厚了),不免在前期出现错误,随着对此书的深入我会在修改前面的错误,也希望各位牛人给予指点。帮助我成长。 sk_buff分析: sk_buff是Linux网络代码中最重要的结构体之一。它是Linux在其协议栈里传送的结构体,也就是所谓的“包”,在他里面包含了各层协议的头部,比如et

jasenwan88的专栏 1008

[linux]sk_buff结构体详解

linux内核sk_buff结构体详解,从sk_buff结构到流程详细讲解sk_buff结构体

yolov8的Detect层详解(输出维度改动)

对于部署端需要拿到onnx的output进行后处理,但是基于anchor_free的yolov8输出是1*(4+cls)*8400,不是我们常见的ncwh格式,所以对Detect层进行了学习,分享一下体会。

yjcccccc的博客 2万+

计算机网络 之 【TCP协议】(面向字节流、TCP异常情况、保活机制、文件与Socket的关系、网络协议栈的本质)

现代网络协议栈在接收数据时,通过DMA将数据直接写入内存缓冲区,各层(数据链路层、网络层、传输层)的解包操作仅依赖移动指针(如sk_buff中的data指针)和偏移量计算来逐层剥离协议头,从而避免对数据本身的多次拷贝,实现了内核层面的高效处理,但最终通过 read/recvfrom 将数据从内核缓冲区拷贝到用户空间仍需要一次不可避免的 CPU 拷贝。网络保活机制的核心是:在长连接空闲时,主动发送极小探测包来确认对端和中间设备(防火墙、NAT等)的连接状态仍有效,防止因超时而误判连接已死。

zl_dfq的博客 918

银河麒麟桌面操作系统V10(SP1)ssh服务安装与配置

在国产化的大背景下,各种国产操作系统逐步进入运维人员的视野,ssh作为linux远程连接工具,是运维人员必需的工具之一。本文主要介绍在银河麒麟桌面操作系统V10(SP1)上安装和配置ssh服务。

zhengshaolin128的博客 7811

【linux的skb的基本操作】

skb_clone是部分数据拷贝:原有的skb->data区域数据共享,dataref++引用计数增加;指针:skb->head | skb->data | skb->tail | skb->end。if (skb_cloned(skb)) { // 检查 cloned 标志。pskb_copy:部分拷贝,只拷贝skb_buff中线性数据区,分片数据任然共享。2、tcp的重传处理,此时用skb_clone()合适。这四个函数是操作数据区域最基础的工具,它们只移动指针,不拷贝数据。

560

RAGFlow核心引擎DeepDoc之PDF解析大起底

本文深入解析RAGFlow中的deepdoc模块,重点介绍了pdf文档解析器的实现细节。deepdoc包含parser(文档解析器)和vision(视觉处理)两大核心功能,其中pdf解析是最复杂的部分。文章详细剖析了PdfParser类的设计架构,包含PlainParser(基础文本提取)、RAGFlowPdfParser(核心处理流水线)和VisionParser(视觉扩展)三个类,它们通过统一的__call__方法返回标准化结果。还具体讲解了初始化过程如何加载OCR引擎、布局识别模型、表格结构识别器等关

yxkong的专栏 2026

Spring Boot 3.5.4 + LangChain4j实战:用Milvus搭建企业级RAG问答系统(附阿里百炼API配置)

本文详细介绍了如何利用Spring Boot 3.5.4、LangChain4j与Milvus构建企业级RAG问答系统。内容涵盖从架构设计、阿里百炼API安全配置、Milvus部署优化,到RAG检索、会话管理等核心实现,并提供了生产级API设计、监控集成及性能优化等实战经验,旨在帮助开发者打造高可用、可维护的Java AI应用。

weixin_29054399的博客 610

Linux内核网络驱动框架

超详细!

qq_28576837的博客 701

手把手教你配置微信商户平台IP白名单:企业付款到零钱必备步骤

本文详细解析了微信商户平台IP白名单的配置原理与实操步骤,这是实现企业付款到零钱功能的关键安全环节。文章从理解IP白名单的安全逻辑出发,指导开发者精准定位服务器公网IP,并提供了在商户平台后台的详细配置流程与常见问题排查指南,帮助开发者高效完成配置,确保企业付款API的顺利调用。

weixin_29326909的博客 737

非常详细的详谈struct sk_buff

非常详细的详谈struct sk_buff 排版太慢 难看的话可以下载WOR文档 专门详解struct_sk_buff 链接: http://pan.baidu.com/s/1gf8VNKR 密码: pquc 注:本文大部分内容来源于网络收集加上自己理解,如有不托之处,请指出,本人无任何版权! 全称socket buffers,简称skb,中文名字叫套接字缓存。它作为网络数据包

zhuhuibeishadiao 1万+

深度学习实战102-基于深度学习的网络入侵检测系统,利用各种AI模型和pytorch框架实现网络入侵检测

在明确了研究背景后,我们需要设定明确的项目目标。本项目的核心目标是开发一个高精度、低延迟的网络入侵检测系统检测准确率:达到95%以上,确保系统能够有效识别各类已知和未知的入侵行为。响应时间:控制在毫秒级范围内,以实现实时监测和快速响应。模型鲁棒性:在面对不同类型的网络环境和攻击手法时,系统需保持稳定的性能输出。可扩展性:系统设计需考虑未来可能面临的新型威胁,便于后续升级和维护。

微学AI的博客 1793

【QT开发教程】Qt中的跨平台文件系统操作

文件系统操作是应用程序开发中经常需要处理的任务。Qt提供了一套跨平台的文件系统操作API,使开发者能够在不同操作系统上无缝地进行文件和目录操作。本文将介绍Qt中的跨平台文件系统操作,包括基本概念、常用类和方法以及实际示例。

科技改变人类,技术成就未来 981

struct sk_buff与struct socket及struct sock 结构体分析

sk_buff是Linux网络协议栈最重要的数据结构之一,该数据结构贯穿于整个数据包处理的流程。由于协议采用分层结构,上层向下层传递数据时需要增加包头,下层向上层数据时又需要去掉包头。sk_buff中保存了L2,L3,L4层的头指针,这样在层传递时只需要对数据缓冲区改变头部信息,并调整sk_buff中的指针,而不需要拷贝数据,这样大大减少了内存拷贝的需要。 /** * struct sk

wangpengqi的专栏 5489

Python爬虫实战:逆向工程与异步爬虫技术,高效抓取国家知识产权局专利数据

相比于传统的Selenium,Playwright由微软开发,支持多浏览器(Chromium, Firefox, WebKit),API更现代,执行速度更快,并且能轻松录制用户操作生成代码。通常,列表中的摘要信息是缩略的,我们需要进入每个专利的详情页获取完整信息(如主权要求、法律状态等)。我们的第一步是手动操作一遍搜索流程,并用Playwright的“录制”功能或开发者工具,找出真正返回专利数据的那一个或多个网络请求。以友好的、对人类行为模拟的方式爬取数据是基本的网络礼仪,也能有效避免你的IP被封锁。

2201_76125261的博客 2420

内核中struct sk_buff结构分析

struct sk_buff可能是linux网络代码中最重要的数据结构,它表示接收或发送数据包的包头信息,并包含很多成员变量供网络代码中的各子系统使用。 这个结构被网络的不同层(MAC或者其他二层链路协议,三层的IP,四层的TCP或UDP等)使用,并且其中的成员变量在结构从一层向另一层传递时改变。 L4向L3传递前会添加一个L4的头部,同样,L3向L2传递前,会添加一个L3的头部。添加头部比在不同

Macross的专栏 2505

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

socket、sock、sk_buff的关系

在Linux2.6中,struct sk_buf承担了socket的输入输出的传输缓存的任务。 首先,还是先看struct socket的定义 /** * struct socket - general BSD socket * @state: socket state (%SS_CONNECTED, etc) * @type: socket type (...

Tasdily的博客 2002

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

struct sk_buff 结构

struct sk_buff可能是linux网络代码中最重要的数据结构,它表示接收或发送数据包的包头信息,并包含很多成员变量供网络代码中的各子系统使用。 这个结构被网络的不同层(MAC或者其他二层链路协议,三层的IP,四层的TCP或UDP等)使用,并且其中的成员变量在结构从一层向另一层传递时改变。 L4向L3传递前会添加一个L4的头部,同样,L3向L2传递前,会添加一个L3...

LetsFl1988的专栏 281

struct sk_buff(2)

 LINUX网络协议栈实现分析(-)SKBUFF的实现本文是我尝试分析LINUX网络协议栈实现的一系列文章中的第一篇,主要分析LINUX网络协议栈中SKBUFF的实现。分析以LINUX2.2.x为基础,同时也包括了相同的描述对象在LINUX2.4.x中的新变化。本文引用的代码的版本分别是:LINUX2.2.25,LINUX2.4.20。1 简介了解网络协议栈的人都知道,网络协议栈是一个有层次的软件

thomasCJ的专栏 1629

struct sk_buff分析

作者:独孤九贱struct sk_buff {<br />    struct sk_buff    * next;                <br />         struct sk_buff    * prev;            <br />    struct sk_buff_head * list;        <br />    struct sock    *sk;            <br />    struct timeval    stamp;          

zhangx105504的专栏 706
上一篇: LINUX中断机制与信号
下一篇: Linux应用程序之文件
小飞鱼hubble
博客等级 码龄15年 14粉丝 8原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值