0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核中的jump label原理与逻辑及运行过程

Linux阅码场 来源:CSDN技术社区 作者:dog250 2021-03-25 14:02 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

jump label机制进入Linux内核已经很多很多年了,它的目的是 消除分支。 为了达到这个目的,jump label的手段是 修改分支处的代码。

~把代码当做数据,代码和数据在冯诺伊曼计算机中得到了统一~

本质上,jump label作用于下面的逻辑:

e0bbcc26-8cdd-11eb-8b86-12bb97331649.png

静态拆分成了下面的两个逻辑,其一是:

e0e058fc-8cdd-11eb-8b86-12bb97331649.png

或者,其二是:

e12ea246-8cdd-11eb-8b86-12bb97331649.png

但二者不能同时共存。显然,这破坏了通用性和灵活性,带来了高效!

这相当于一个硬熔断,具体详情参见:

本文来一点可以看得见的东西,演示一下真实的jump label & static key。

先看下面的C代码:

e1519dc8-8cdd-11eb-8b86-12bb97331649.png

很简单的代码,也很正确。然而, 如果main函数是一个高频调用的函数,并且在E1,E2是不随着代码逻辑而发生变化,仅仅参数设定的情况下, 那么if语句尽量消除以消除不必要的分支预测,而这正是jump label的用武之地!

我们下面用jump label机制来重写上面的代码,请看:

e18ee192-8cdd-11eb-8b86-12bb97331649.png

e1e3bc44-8cdd-11eb-8b86-12bb97331649.png

e22b2692-8cdd-11eb-8b86-12bb97331649.png

e26cc53e-8cdd-11eb-8b86-12bb97331649.png

e2a16848-8cdd-11eb-8b86-12bb97331649.png

定义JUMP_LABEL宏编译之,看看效果:

e2c8bb50-8cdd-11eb-8b86-12bb97331649.png

如何做到的呢?static_branch_true内联函数是如何判断true or false的呢?

事实上,jump label逻辑修改了代码段,取消了条件判断!这一切都是在update_branch中发生的。我们看下update_branch调用之前,main函数的汇编码:

e31df26e-8cdd-11eb-8b86-12bb97331649.png

在执行了update_branch之后,main函数发生了变化:

e338ed80-8cdd-11eb-8b86-12bb97331649.png

e39d2124-8cdd-11eb-8b86-12bb97331649.png

看样子就是这么回事!

之所以这件事可以发生得如此简单,多亏了一个新的section,即__jump_table,我们通过objdump看看__jump_table的内容:

e3e7c74c-8cdd-11eb-8b86-12bb97331649.png

通过jump_label_demo.c的struct entry结构体,我们直到这个section中包含了多个3元组,包含3个字段:

需要修改的代码地址。

需要jmp到的代码地址。

匹配健。

我们看67064000 00000000按照小端就是0x400667,它就是需要修改的代码地址,而6e064000 00000000按照小端则是0x40066e:

e41fa0e0-8cdd-11eb-8b86-12bb97331649.png

看来,这个__jump_table的item会将jmpq 40066c修改为jmpq 40066e,从而实现了 永久静态分支。

最后,__jump_table的内容就是在每一个内联的static_branch_true函数中被填充的,该参数的参数是一个key,它指示了branch entry三元组中的最后一个字段。

static_branch_true函数的内联非常重要,它实现了将branch entry三元组数据直接插入到__jump_table section,而不是共享同一个函数体。

总之,如果你看代码还是觉得别扭,手敲一遍我上面的示例程序,就理解了,内核里面的也就这么回事,总结一句话:

依靠运行时修改代码而不是依靠状态数据来控制执行流。

我不知道这对于所谓的 通用计算机程序设计 是不是反其道而行之,但在效果上,它确实是一匹好马。不禁感叹, 硬编码读起来是丑陋的,但执行起来却是高效的!

灵活性换高效率,得不偿失,我是这样以为。jump label的本质在于, 将同时刻存在的一套代码沿着时间线在可预期的固定时间点上分割成逻辑相反的两套代码。

硬件性能的提升将会证明jump label就是个笑话。

说两句好话,Linux内核参数,sysctl变量基本上就可以通过jump label来运作,从而替代if判断。

原文链接:https://blog.csdn.net/dog250/article/details/106715700
编辑:lyn

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    7366

    浏览量

    95178
  • 逻辑
    +关注

    关注

    2

    文章

    834

    浏览量

    30207
  • 代码
    +关注

    关注

    30

    文章

    4985

    浏览量

    74565
  • LINUX内核
    +关注

    关注

    1

    文章

    321

    浏览量

    23334

原文标题:Linux内核jump label与static key的原理与示例

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    openKylin受邀参加Linux内核领域顶级技术峰会

    近日,Linux内核领域顶级技术峰会——LSF/MM/BPF 2026在克罗地亚萨格勒布举行。大会聚焦Linux内核存储、文件系统、内存管理以及BPF等关键技术方向,吸引了来自全球开源
    的头像 发表于 05-14 11:08 567次阅读

    如何理解Linux内核的PCIe驱动

    各异的芯片组,加上各种 PCI 设备自身独特的功能需求,Linux 内核的 PCI 支持远比我们希望的要复杂得多。今天这篇文章,我们将从驱动开发的视角,梳理 Linux PCI 设备
    的头像 发表于 04-11 17:22 1426次阅读

    Linux内核驱动开发的技术核心精要

    开发必须理解的技术要点,供从业者参考。 一、并发与同步:多核系统的根基 现代内核默认支持SMP(对称多处理),驱动代码可能同时运行在多个CPU核、中断、软中断、抢占路径上,竞态风险无处不在。
    发表于 03-10 13:56

    Linux内核伙伴系统内存申请函数详解:从原理到实战

    Linux 内核,内存管理是整个系统稳定运行的基石,而伙伴系统(Buddy System) 作为内核物理内存分配的核心机制,更是驱动开
    的头像 发表于 02-10 16:58 3778次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>伙伴系统内存申请函数详解:从原理到实战

    Linux内核的“心跳”:jiffies如何为系统计时?

    Linux 内核的世界里,有一个默默工作的 "计时器"——jiffies。它不像我们手机上的时钟那样显示年月日,却掌控着内核绝大多数时间相关的操作:从进程调度到设备驱动的定时检查
    的头像 发表于 02-04 16:27 989次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>的“心跳”:jiffies如何为系统计时?

    深入RK3588内核:rockchip_linux_defconfig的作用与调试价值

    在 RK3588 芯片的 Linux 开发,有一个文件始终是开发者绕不开的核心 ——kernel/arch/arm64/configs/rockchip_linux_defconfig。无论是首次
    的头像 发表于 02-03 15:56 1473次阅读
    深入RK3588<b class='flag-5'>内核</b>:rockchip_<b class='flag-5'>linux</b>_defconfig的作用与调试价值

    【「Linux 设备驱动开发(第 2 版)」阅读体验】+读深入理解Linux内核内存分配

    每个内存地址是虚拟的,不是直接指向RAM的任何地址。当用户访问内存的存储单元时,都会进行地址转换以匹配相应的物理内存。书籍的第10章讨论了五个主题,对Linux内核内存分配进行详细
    发表于 01-16 20:05

    【「Linux 设备驱动开发(第 2 版)」阅读体验】Linux内核开发基础

    感谢电子发烧友论坛提供的《Linux设备驱动开发(第2版)》阅读机会,测评将从Linux内核开发基础、Linux内核平台抽象和设备驱动程序、
    发表于 01-12 22:45

    深入Linux内核:进程调度的核心逻辑与实现细节

    ,背后都离不开内核调度算法的精准操控。今天,我们就从优先级、调度算法、时间片分配到底层实现,全方位拆解Linux内核进程调度的核心逻辑。 一、进程调度的“身份标识”:优先级与分类 要理
    的头像 发表于 12-24 07:05 4724次阅读
    深入<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>:进程调度的核心<b class='flag-5'>逻辑</b>与实现细节

    探索操作系统底层的关键接口

      在linux,将程序的运行空间分为内核空间与用户空间(内核态和用户态),在逻辑上它们之间是
    的头像 发表于 11-08 12:42 941次阅读

    deepin亮相2025Linux内核开发者大会

    11 月 1 日,第二十届中国 Linux 内核开发者大会(CLK)在深圳举办。CLK 作为国内 Linux 内核领域极具影响力的峰会,由清华大学、Intel、华为、阿里云、富士通南大
    的头像 发表于 11-05 17:59 998次阅读

    使用rk3568开发板,核0\\1\\3运行linux,核2运行hal,在核0怎么关闭核2

    使用rk3568开发板,核0\\\\1\\\\3运行linux,核2运行hal,想在内核通过smc指令完成核0对核2得启动和关闭,文件系统
    发表于 10-27 10:09

    如何在裸机环境运行KleidiAI微内核

    ,对 KleidiAI 进行了简要概述,并附有相关指南链接,其中详细说明了在 Linux 环境运行 KleidiAI 矩阵乘法 (matmul) 微内核的分步操作,这份指南内容详实且
    的头像 发表于 08-08 15:16 4107次阅读
    如何在裸机环境<b class='flag-5'>中</b><b class='flag-5'>运行</b>KleidiAI微<b class='flag-5'>内核</b>

    Linux内核参数调优方案

    在高并发微服务环境,网络性能往往成为K8s集群的瓶颈。本文将深入探讨如何通过精细化的Linux内核参数调优,让你的K8s节点网络性能提升30%以上。
    的头像 发表于 08-06 17:50 1254次阅读

    如何配置和验证Linux内核参数

    Linux系统运维和性能优化内核参数(sysctl)的配置至关重要。合理的参数调整可以显著提升网络性能、系统稳定性及资源利用率。然而,仅仅修改参数是不够的,如何验证这些参数是否生效同样关键。
    的头像 发表于 05-29 17:40 1496次阅读