Linux 内核中的 static_key 机制

深入解析Linux内核中的tracepoint机制及其应用场景 本文深入解析Linux内核中的tracepoint机制,详细介绍了其基础概念、事件声明与TRACE_EVENT宏的设计演进,以及核心数据结构和实现机制。通过实战应用案例,展示了tracepoint在性能分析、动态过滤和与BPF结合中的高效应用,帮助开发者优化内核调试和性能监控。 阅读详情

目录

 

问题来源:恶意程序检测

DO_ONCE函数解析

STATIC KEYS

GOTO

JUMP TABLE

__do_once_done

CONFIG

 问题解决:


问题来源:恶意程序检测

最近,主要由于在研讨一些关于LINUX被恶意程序ROOT后,可能会被修改代码段中的数据。为了防止代码段被修改,采用几种特殊的机制来保护代码段的数据不被篡改,当有恶意程序试图修改代码段或只读数据段中的数据,特殊保护机制会自动忽略这种恶意操作,并追溯该操作的PC地址,栈指针,进程号等,从而找到恶意程序的源头,从而处理恶意程序。

问题就是来源这种特殊的保护机制启动后,当安装一些官方验证后的APK后,我们发现保护机制居然真的报警了,这意味着有程序在修改代码段。起初我们怀疑该APK自带ROOT工具,但是后来通过特殊机制进行回追出错的地址,回溯栈指针,发现是由于LINUX系统引入了Static_Keys机制,该机制中的部分函数的实现利用了代码段修改来实现的,而不是每次都是通过变量判断,从而直接改变代码段。而修改代码段的工作就交给了一个函数就是DO_ONCE中的__do_once_done中,那么我们就先来分析一下代码。

DO_ONCE函数解析

DO_ONCE机制想法很简单,有些函数只应该调用一次,那么这些函数调用一次后,如果下次再调用就应该直接返回。以前我们要实现这种功能总是需要判断一个变量,而使用DO_ONCE机制,自动帮你完成判断,保证函数只会在第一次调用的时候被执行,以后都直接返回。很自然,DO_ONCE机制就采用了Static_Keys来实现。使用static_key外 ,另一个关键在__do_once_done中。

#define DO_ONCE(func, ...)						     \
	({								     \
		bool ___ret = false;					     \
		static bool ___done = false;				     \
		static DEFINE_STATIC_KEY_TRUE(___once_key);		     \
		if (static_branch_unlikely(&___once_key)) {		     \
			unsigned long ___flags;				     \
			___ret = __do_once_start(&___done, &___flags);	     \
			if (unlikely(___ret)) {				     \
				func(__VA_ARGS__);			     \
				__do_once_done(&___done, &___once_key,	     \
					       &___flags);		     \
			}						     \
		}							     \
		___ret;							     \
	})

如果有一个func只能被调用一次,例如初始化函数的话,则可以用这个宏,如下例所示foo这个函数即使被调用两次,也只会运行一次:

/* Call a function exactly once. The idea of DO_ONCE() is to perform
 * a function call such as initialization of random seeds, etc, only
 * once, where DO_ONCE() can live in the fast-path. After @func has
 * been called with the passed arguments, the static key will patch
 * out the condition into a nop. DO_ONCE() guarantees type safety of
 * arguments!
 *
 * Not that the following is not equivalent ...
 *
 *   DO_ONCE(func, arg);
 *   DO_ONCE(func, arg);
 *
 * ... to this version:
 *
 *   void foo(void)
 *   {
 *     DO_ONCE(func, arg);
 *   }
 *
 *   foo();
 *   foo();
 *
 * In case the one-time invocation could be triggered from multiple
 * places, then a common helper function must be defined, so that only
 * a single static key will be placed there!
 */

STATIC KEYS

简单的说,如果你代码对性能很敏感,而且大多数情况下分支路径是确定的,可以考虑使用Static Keys。Static Keys可以代替使用普通变量进行分支判断,目的是用来优化频繁使用if-else判断的问题,这里涉及到指令分支预取的一下问题。简单地说,现代cpu都有预测功能,变量的判断有可能会造成硬件预测失败,影响流水线性能。虽然有likely和unlikely,但还是会有小概率的预测失败。

下面使用例子说明一下:

//定义一个Static Keys,并且默认这个值是false。
DEFINE_STATIC_KEY_FALSE(key);…
//代码使用Static Keys代替普通变量进行判断,static_branch_unlikely是一个宏,展开后不会有真正的判断,而是直接执行false分支,即 do likely code。
if (static_branch_unlikely(&key))
    do unlikely code
else
    do likely code… 

这样的好处是,上述代码的性能和没有分支判断的性能差不多,具体可能只差一个nop指令的执行时间。 当然,如果某种情况发生了,需要改变分支的执行路径,可以调用下面的接口:
static_branch_enable(&key);
执行static_branch_enable(&key)后,底层通过gcc提供的goto功能,再结合c代码编写的动态更改内存功能,就可以让使用key的代码从执行false分支变为执行true分支。当然这个更改代价是比较昂贵的,不是所有情况都适用。可以改变分支的函数参照如下

#define static_branch_inc(x)		static_key_slow_inc(&(x)->key)
#define static_branch_dec(x)		static_key_slow_dec(&(x)->key)
#define static_branch_inc_cpuslocked(x)	static_key_slow_inc_cpuslocked(&(x)->key)
#define static_branch_dec_cpuslocked(x)	static_key_slow_dec_cpuslocked(&(x)->key)

/*
 * Normal usage; boolean enable/disable.
 */

#define static_branch_enable(x)			static_key_enable(&(x)->key)
#define static_branch_disable(x)		static_key_disable(&(x)->key)
#define static_branch_enable_cpuslocked(x)	static_key_enable_cpuslocked(&(x)->key)
#define static_branch_disable_cpuslocked(x)	static_key_disable_cpuslocked(&(x)->key)

GOTO

gcc4.5提供了一个特性用于嵌入式汇编,那就是asm goto,其实这个特性没有什么神秘之处,就是在嵌入式汇编中go to到c代码的label,其最简单的用法如下(来自gcc的文档):
int frob(int x)
{
    int y;
    asm goto ("frob %%r5, %1; jc %l[error]; mov (%2), %%r5"
                 : : "r"(x), "r"(&y) : "r5", "memory" : error);
    return y;
error:
    return -1;
}

按照原理来说"asm goto"其实就是在outputs,inputs,registers-modified之外提供了嵌入式汇编的第四个“:”,后面可以跟一系列的c语言的label,然后你可以在嵌入式汇编中goto到这些label中一个。然而使用"asm goto"可以巧妙地将"运行时修改载入内存的二进制代码”规范化,就是说你只需要调用一个统一的接口宏,编译器就将你想实现的东西给实现了,要不然代码写起来会很麻烦,这点上,编译器不嫌麻烦。具体为什么要动态修改二级制代码的原因还是与前面介绍的指令分支预取有关,为了极大的优化系统性能。

JUMP TABLE

jump_lable屏蔽不同体系更改机器代码的不同,向上提供一个统一接口。不同体系会提供给jump_lable一个体系相关的实现。
jump_lable的实现原理很简单,就是通过替换内存中机器代码的"nop"空指令为"b"指令,或者替换机器代码的“b”指令为“nop”空指令,实现分支的切换.

static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{
	asm goto("1: nop\n\t"
		 ".pushsection __jump_table,  \"aw\"\n\t"
		 ".align 3\n\t"
		 ".quad 1b, %l[l_yes], %c0\n\t"
		 ".popsection\n\t"
		 :  :  "i"(&((char *)key)[branch]) :  : l_yes);

	return false;
l_yes:
	return true;
}

static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
{
	asm goto("1: b %l[l_yes]\n\t"
		 ".pushsection __jump_table,  \"aw\"\n\t"
		 ".align 3\n\t"
		 ".quad 1b, %l[l_yes], %c0\n\t"
		 ".popsection\n\t"
		 :  :  "i"(&((char *)key)[branch]) :  : l_yes);

	return false;
l_yes:
	return true;
}

__do_once_done

void __do_once_done(bool *done, struct static_key_true *once_key,
		    unsigned long *flags)
	__releases(once_lock)
{
	*done = true;
	spin_unlock_irqrestore(&once_lock, *flags);
	once_disable_jump(once_key);
}
EXPORT_SYMBOL(__do_once_done

这个函数实在执行完第一次—do_once_start后需要修改代码段将jump修改成nop,最后还是调用了static_branch_disable(work->key); 具体修改代码段的代码追溯后到arch_jump_label_transform:

void arch_jump_label_transform(struct jump_entry *entry,
			       enum jump_label_type type)
{
	void *addr = (void *)entry->code;
	u32 insn;

	if (type == JUMP_LABEL_JMP) {
		insn = aarch64_insn_gen_branch_imm(entry->code,
						   entry->target,
						   AARCH64_INSN_BRANCH_NOLINK);
	} else {
		insn = aarch64_insn_gen_nop();
	}

	aarch64_insn_patch_text(&addr, &insn, 1);
}

 再次调用aarch64_insn_patch_text_nosync函数,

int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn)
{
	u32 *tp = addr;
	int ret;

	/* A64 instructions must be word aligned */
	if ((uintptr_t)tp & 0x3)
		return -EINVAL;

	ret = aarch64_insn_write(tp, insn);
	if (ret == 0)
		flush_icache_range((uintptr_t)tp,
				   (uintptr_t)tp + AARCH64_INSN_SIZE);

	return ret;
}

最后调用到__aarch64_insn_write,进行代码段的重映射,然后将jump tabel的头地址“b ”替换成“nop”,取消映射,返回。

static int __kprobes __aarch64_insn_write(void *addr, __le32 insn)
{
	void *waddr = addr;
	unsigned long flags = 0;
	int ret;

	raw_spin_lock_irqsave(&patch_lock, flags);
	waddr = patch_map(addr, FIX_TEXT_POKE0);

	ret = probe_kernel_write(waddr, &insn, AARCH64_INSN_SIZE);

	patch_unmap(FIX_TEXT_POKE0);
	raw_spin_unlock_irqrestore(&patch_lock, flags);

	return ret;
}

作为安全工程师,linux提供这种可以修改的代码段的函数,如果是用于调试还可以理解,但是如果公布的版本还是提供,是不是给一些专家提供了便捷的途径,还是那句话,"安全是一个平衡,性能和安全从来就是相对的,具体看应用的场景吧“。

CONFIG

如果启动功能,需要在开启线面的两个开关,目前Linux在x86上是强制开启的,ARM上还是根据需求来开启。

#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
# define HAVE_JUMP_LABEL
#endif

 问题解决:

最后,我先关掉了这个开关,特殊代码段检测程序已经不会再检测到有人修改的异常了。稍后,我会对这种修改做特殊处理,但是需要特殊识别,我的程序又要复杂了。

Linux内核Jump Labels机制:零开销动态代码路径切换原理与实践 在Linux内核开发中,性能优化是核心议题,尤其是在高频执行的热路径上,传统的条件分支判断会带来不可忽视的开销。代码自修改技术作为一种底层优化手段,通过运行时动态重写指令,能够将条件判断转化为近乎零成本的静态跳转,从而显著提升系统性能。这种技术在内核的跟踪点、性能事件监控等场景中具有重要价值,是实现生产环境高性能与调试灵活性平衡的关键。Jump Labels机制正是这一思想的典范实现,它利用静态键管理,结合RCU同步和断点指令,安全高效地实现了运行时代码路径的动态切换,为内核开发者提供了强大的性能优化工具。 阅读详情

相关推荐

内核static_branch_likely、likely及inline相关优化实验

static_branch_likely,static_branch_unlikely,likely,unlikely,分支预测,inline,icache

zhaoxin1989的博客 3916

linux内核静态static,Linux内核中的static-key机制

# Linux内核中的static-key机制背景在移植某个TP时,发现频繁操作屏幕会导致i2c总线死掉。在跟踪代码的时候,我发现了这个static-key。因此,学习一下这块的知识。reference:介绍内核的static-key用来优化if-else频繁判断的问题.使用#define DEFINE_STATIC_KEY_FALSE(name) \struct static_key_fa...

weixin_31211821的博客 912

黑客渗透测试后门隐藏技术揭秘

本文介绍了在授权渗透测试中隐藏后门文件(muma.exe)的多种技术手段。主要包括:通过WinRAR自解压脚本将后门与正常程序捆绑实现双开;利用系统自动运行目录和注册表实现开机自启;修改文件图标伪装成常用软件;将文件存放在冷门系统目录;设置系统+隐藏双重属性增强隐蔽性。此外还涉及对抗安全软件的加壳(UPX)、免杀(msfvenom编码)技术,以及进程注入、日志清除等运行隐藏方法。所有技术仅限合法授权测试使用,未经授权使用将面临法律责任。

m0_60781580的博客 1040

jump label

这段代码的反汇编如下所示 static inline bool test_idle_cores(int cpu, bool def) { struct sched_domain_shared *sds; if (static_branch_unlikely(&sched_smt_present)) { sds = rcu_dereference(per_cpu(sd_llc_shared, cpu)); .

jason的笔记 965

从《新程序员》系列看程序员职业发展趋势与成长路径

在信息技术日新月异的当下,软件开发行业蓬勃发展,程序员作为行业的核心力量,其成长与发展路径备受瞩目。《新程序员》系列杂志应运而生,以其前瞻性的视角、丰富多元的内容,为广大程序员尤其是新程序员提供了洞察行业趋势、学习前沿技术、汲取前辈经验的宝贵窗口。该系列杂志由优快云精心打造,自推出以来,便在开发者群体中引发了强烈反响。《新程序员》系列内容涵盖了从基础技术知识的深入解读,到行业前沿趋势的精准预测;从优秀开发者的成长历程分享,到各大企业数字化转型的实践案例剖析等多个维度。

AllenLV的博客 2254

解决turmex安装kali报错问题

在手机上安装好turmex后,都喜欢安装一个Linux系统,我当时安装的时kali,但是安装过程中,报错不断。 2019.8.24更新 1,出现问题首先看下载kali源文件是否完整 安装步骤中,会显示[解压中.....] ,可以看到解压的大小。 如图所示,完整源文件不小于81M。 如果源文件过小,则说明下载错误,而且在remove kali这个命令下,是不会删除源文件的,下一次安装只...

WeiLuckyStrike的博客 1万+

linux DO_ONCE、Static Keys、jump label和IPI

本文基于linux4.4 问题的来源: 研究的起始来源与发现linux4.4内核在x86机器上text_poke_bp函数会向每个在线cpu发送IPI,执行do_sync_core动作。 虽然do_sync_core只是在每个cpu上执行一下简单的CPUID指令,但毕竟会触发中断,打断当前进程,对系统确定性造成影响。 下面主要分析下这个IPI的来龙去脉。 一种分支判断优化方法: 要说明...

wdjjwb的专栏 1589

【PyBind11+anaconda+opencv+windows11+cmake+wsl+vscode】从入门到跑通。构建基于opencv c++的python package

如何安装请详见上文 【PyBind11+anaconda+opencv+windows11+cmake+wsl+vscode】从入门到跑通。构建基于opencv c++的python接口_子韵如初的博客-优快云博客w不需要安装啥x11 、 xming直接mobxterm可以搞定点击右上角的X server打开可视化服务器然后 apt install x11-apps -yxclock 搞定从mobxterm可以看到display的端口X11显示可视化的原理是就是通过X协议,类似于http对linux于w

weixin_43953700的博客 3万+

static_branch_likely 原理及用法(完全剖析)

看irq-gic-v3.c时,发现中断回调中有static_branch_likely 这么一个函数。看起来是为了减少cpu 分支预测失败带来的巨大代价而做的优化。具体原理还没细看。 内核源码中这里有个文档介绍 kernel/Documentation/static-keys.txt。 ...

weixin_43512663的博客 2464

AS7262六通道可见光传感器:从光谱原理到物联网色彩检测实战

光谱检测是嵌入式感知领域的关键技术,其核心原理是通过特定波长的滤光片分离光线并转换为电信号,从而实现对环境光或物体反射光的成分分析。这项技术的价值在于将复杂的光学分析简化为可编程读取的数字信号,极大降低了色彩检测在物联网和智能设备中的应用门槛。在智能农业、工业分拣、环境监测等场景中,精确的光谱数据能够驱动自动化决策,例如评估植物光照条件或识别物料颜色。本文以Adafruit AS7262传感器为例,深入解析其基于硅干涉滤光片的六通道设计,并通过Arduino与Python实战,演示如何快速构建从数据采集到可

weixin_28738173的博客 595

[医学图像分割综述] Medical Image Segmentation Using Deep Learning: A Survey

本综述有两个独创之处,首先,与传统的调查方法直接将医学图像分割的文献划分为多个组,并对每个组详细介绍文献的方法相比,我们将目前流行的文献按照从粗到细的多层次结构进行分类。其次,本文重点研究了监督学习和弱监督学习方法,但未包括无监督方法,这种方法目前在医学图像领域并不流行。对于监督学习方法,我们从骨干网络的选择、网络块的设计和损失函数的改进三个方面对文献进行了分析。对于弱监督学习方法,我们分别根据数据增强,迁移学习和交互式分割研究文献。与已有的调查相比,本次调查的文献分类与以往有很大的不同,更便于读者了解相关

qq_38932073的博客 4万+

linux 内核 static-key机制分析

地址4字节对齐,意味着地址的低2位总是为0,正是利用这一点,struct static_key::type用低位的2位来存储相关struct jump_entry(即static_key::entries指向的struct jump_entry)的类型。当arch_static_branch/arch_static_branch_jump()函数被编译时,内嵌汇编中1:标签处的内容为nop指令或者b指令在内核的代码段中,内核加载时,其被加载到内存中的某个地址上。

Amelio Ming 1328

记一次在JAVA中客户端使用axis调用webservice服务端出现的异常:Unmarshalling Error: For input string: ""

在使axis调用webservice服务端,参照网上给的demo: Call call = (Call) service.createCall(); call.setTargetEndpointAddress(endpoint);//设置服务请求路径 QName qn = new QName(name); call.setOperationName(qn); call.addParamet

kry1201的专栏 8079

Linux Static Key原理与应用

内核中有很多判断条件在正常情况下的结果都是固定的,除非极其罕见的场景才会改变,通常单个的这种判断的代价很低可以忽略,但是如果这种判断数量巨大且被频繁执行,那就会带来性能损失了。

chi's blog 1203

智能车图像处理0-图像处理整体框架思路

1.总体框架如上所示,具体代码请查看后续文章。2.因为参与竞赛时间是大二,所以在编程中有许多不规范的地方(如变量的命名),大家见谅。3.原创文章,请勿侵权=-=

taiyuezyh的博客 1万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Linux Jump Label/static-key机制详解

Linux Jump Label/static-key机制详解 RToax 2021年3 关于Linux Jump Label(x86)已经进行过概述,下面就static-key进行详述。 内核中有很多判断条件在正常情况下的结果都是固定的,除非极其罕见的场景才会改变,通常单个的这种判断的代价很低可以忽略,但是如果这种判断数量巨大且被频繁执行,那就会带来性能损失了。内核的static-key机制就是为了优化这种场景,其优化的结果是:对于大多数情况,对应的判断被优化为一个NOP指令,在非常有场景的时候就

RToax 2498

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Linux Static Keys和jump label机制

Linux Static Keys和jump label机制简介

小立仔 2117

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

static-key机制

内核的static-key用来优化if-else频繁判断的问题. 如何使用: #define DEFINE_STATIC_KEY_FALSE(name)    \     struct static_key_false name = STATIC_KEY_FALSE_INIT 一般使用DEFINE_STATIC_KEY_FALSE 定义条件不成立的case,用DECLARE_STATIC_

jason的笔记 4553

Linux内核性能优化:Jump Labels与Static Keys原理与实践

在Linux内核开发中,性能优化是核心议题,尤其是在处理频繁执行的热路径代码时。传统条件分支带来的开销,如分支预测失败和跳转指令,可能成为性能瓶颈。Jump Labels技术通过代码动态修补机制,将运行时条件判断转换为近乎零开销的指令替换,从而显著提升性能。其核心原理基于text_poke和stop_machine机制,允许内核在运行时原子地替换NOP与跳转指令。这一技术在内核中通过Static Keys接口暴露给开发者,广泛应用于调试信息打印、性能计数器、特定硬件支持等场景,实现了功能开关的动态化与性能开

weixin_30421809的博客 446

Linux内核性能优化:Jump Labels机制原理与实践指南

在操作系统内核开发中,性能优化是核心挑战之一,尤其是在处理高频条件判断时。传统if-else分支会引入内存访问、条件判断和分支预测失败等开销,影响系统整体性能。Jump Labels(跳转标签)作为一种底层优化机制,通过将运行时条件判断转换为一次性代码修补,实现了近乎零开销的状态切换。这项技术基于自我修改代码原理,在内核初始化或状态变更时动态重写指令,消除热路径上的分支判断。其技术价值在于为内核追踪、动态调试等场景提供高性能开关,特别适用于状态变化极低频但检查频率极高的场景。通过static_key API

weixin_34109408的博客 401

Linux 内核 static_branch_likely:零开销条件分支

Linux内核中的static_branch_likely机制通过运行时热补丁技术实现零开销条件分支。它适用于频繁检查但很少切换的特性开关(如tracepoint、debug标志),默认情况下将分支指令替换为nop,完全消除分支预测和内存访问开销。使用时需定义static key并配合likely/unlikely宏,运行时通过static_branch_enable/disable切换状态,内核会安全地修改代码段指令。相比普通bool变量,该方案在开关关闭时实现绝对零开销,但切换成本较高,特别适合内核中大

SurpriseDPD的博客 342

Linux Tracepoint 机制深度解析

Linux Tracepoint是一种轻量级动态跟踪机制,通过在关键代码路径插入钩子实现运行时探测。其核心特点是静态定义、动态启用,未启用时仅增加1-2个CPU周期的分支判断开销。相比printk/kprobe等机制,Tracepoint具有类型安全、稳定、低开销等优势。 使用包含三个关键步骤:1) 在内核头文件中定义跟踪点;2) 在源码中插入trace_xxx()调用;3) 运行时通过内核模块或ftrace接口挂载探测函数。

图形/计算GPU的驱动与虚拟化技术分享园地 2906

Linux内核Jump Labels机制:零开销条件判断的实现原理与应用

在操作系统内核开发中,性能优化是永恒的主题。条件分支判断是常见的性能瓶颈,尤其是在高频执行路径中,每次的变量读取和分支跳转都会累积显著开销。Jump Labels(跳转标签)技术通过代码自修改机制,将运行时的条件判断转化为编译时决定的指令补丁,实现了近乎零开销的开关检查。其核心原理是利用特殊的ELF段(.jump_table)记录所有跳转点,在状态切换时通过stop_machine同步修改所有CPU的指令缓存。这项技术特别适用于状态长期不变的场景,如调试功能开关、性能监控点等,通过消除热路径上的分支预测失败

387

Linux内核性能优化:Jump Labels技术原理与实践

在Linux内核开发中,性能优化是核心挑战之一。传统条件分支(如if语句)虽然灵活,但在高频执行路径上会带来显著开销,尤其是当分支条件在运行时极少变化时。Jump Labels(跳转标签)技术通过将动态判断转化为静态跳转,实现了近乎零开销的分支优化。其核心原理是利用编译时生成的可修补指令,在运行时根据static_key的状态动态修改代码段,从而消除不必要的内存读取和比较操作。这项技术对于内核中的调试代码、性能统计和特性开关等场景具有重要价值,能够显著提升系统整体性能。通过理解Jump Labels的实现机

weixin_30294295的博客 353

linux tracepoint系列宏定义(TRACE_EVENT,DEFINE_TRACE等)展开过程分析之一 tracepoint实现原理

linux tracepoint系列宏定义(TRACE_EVENT,DEFINE_TRACE等)展开过程分析之一 tracepoint实现原理。在开始描述之前,我们先介绍下linux tracepoint是什么?以及为什么需要tracepoint? TRACE_EVENT系列宏定义的展开基本上是笔者当前见过的最复杂的宏定义了,没有之一。 1、tracepoint概念         跟踪点(tracepoint)是放置在内核代码中较重要位置的硬编码检测点。例如,在系统调用、调度程序事件、文件系统操作和

Amelio Ming 1219
上一篇: 2.2 C++ 变量
下一篇: [转]深入理解 CPU 的分支预测(Branch Prediction)模型
西瓜凉快
博客等级 码龄16年 6粉丝 4原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值