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结构体

常见消息队列:ActiveMQ、RabbitMQ、RocketMQ、Kafka的区别总结

常见消息队列:ActiveMQ、RabbitMQ、RocketMQ、Kafka的区别。

qq_30713721的博客 3471

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

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

zl_dfq的博客 918

10.2 在新能源、储能及电网节点的应用实践

构网型变流器技术在电力系统中的应用进展 构网型变流器技术正从理论研究走向规模化工程应用,为新能源并网提供主动支撑能力。该技术在光伏电站采用"部分构网"混合架构,由构网单元实现黑启动和弱网稳定;在风电场利用叶轮动能提供惯量响应。储能系统是理想的构网载体,可提供快速调频和动态电压支撑。在电网节点,构网型STATCOM可增强弱电网电压稳定性,大容量变流器可替代传统调相机。当前面临标准滞后、宽频振荡风险等共性挑战,需在可靠性、经济性间取得平衡。系统级协调控制和精确阻抗建模是应用成功的关键。

技术工作者 1112

【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

Win11用户文件夹中文名修改全攻略

本文详细介绍了Windows 11系统中修改中文用户文件夹名称的完整步骤。操作包含七个关键环节:前期数据备份、账户名称修改、管理员账户激活、用户文件夹重命名、注册表路径更新、收尾操作及注意事项。特别强调需要同步修改账户名、文件夹名和注册表关联路径,并建议操作前备份重要数据。文中还针对常见问题提供了解决方案,如软件报错时的符号链接创建方法。整个过程需谨慎操作,建议在管理员权限下逐步执行,修改完成后需验证系统及软件功能是否正常。

Qinti_mm的博客 3123

爬虫:一文掌握 Pydoll 的详细使用(彻底改变浏览器自动化,且能绕过绕过验证码!)

Pydoll正在彻底改变浏览器自动化!与其他解决方案不同,它消除了对Web驱动程序的需求,提供了流畅可靠的自动化体验和本机异步性能。

数据知道的博客 1万+

Linux内核网络驱动框架

超详细!

qq_28576837的博客 701

openlayers6/7 行政区划裁剪 只显示某个区域 示例为天地图

openlayers6/7 行政区划裁剪 只显示某个区域 示例为天地图。

qq_36287830的博客 3104

非常详细的详谈struct sk_buff

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

zhuhuibeishadiao 1万+

ABAP 平台下配置 OAuth 2.0 Authorization Code 授权类型的完整指引

本文是面向ABAP管理员和SAP开发者的OAuth 2.0授权码配置实战指南。文章详细介绍了在ABAP平台启用Authorization Code的完整流程,包括前置条件检查(如TLS配置和系统用户准备)、SOAUTH2事务码中各字段配置要点(授权类型启用、Redirect URI设置、授权码有效期等)、Scope分配规则以及验证方法。通过一个销售订单OData接口的实际案例,说明了如何将抽象规范转化为具体配置。最后提供了多种验证方式(事务码测试、端点测试和Postman测试)以及关键配置参数(如授权码有效

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 298

基于STM32L4XX 、HAL库的ATD5984步进电机驱动器驱动程序应用设计

一、简介: ATD5984是一款内部集成了译码器的微特步进电机 驱动器,能使双极步进电机以全、半、1/4、/1/8、1/16 和1/32步进模式工作。步进模式由逻辑输入管脚MSx选 择。其输出驱动能力达到28V±1.6A。 译码器是ATD5984易于使用的关键,通过STEP管脚 输入一个脉冲就可以使电机完成一次步进,省去了相序 表,高频控制线及复杂的编程接口,使其更适于没有复 杂的微处理器或微处理器负担过重的场合。 在步进操作期间,ATD5984的内部电路可以自动

PP_Cottage的博客 408

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

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

wangpengqi的专栏 5489

CS之攻击菜单详解-后门生成与上线

能够生成如HTA文档、office宏、payload生成器、exe程序。 windows可执行程序exe 可以看到能生成两种windows可执行程序,其分别代表stage分阶段和unstage(stageless)不分阶段。传送门 ——>Cobalt Strike中payload的stage与unstage区别 选择监听器后,按需生成不同类型的exe 然后在目标机器运行即可上线 payload生成器 选择生成如下类型的后门 ——>https://che...

渗透之路,攻防之间皆学问 6808

内核中struct sk_buff结构分析

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

Macross的专栏 2505

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

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

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

struct sk_buff 结构

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

LetsFl1988的专栏 281

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

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、付费专栏及课程。

余额充值