Linux vdso机制

文章目录

  • 一、简介
  • 二、vdso
    • 2.1 用户态
    • 2.2 内核态
    • 2.3 内核源码解析
  • 参考资料

一、简介

Linux中的vdso(Virtual Dynamic Shared Object)是一种特殊的动态共享对象,它在用户空间和内核空间之间提供了一种高效的接口。vdso机制的目的是减少用户空间程序与内核之间频繁的上下文切换开销,提高系统性能。

“vDSO”(虚拟动态共享对象)是一个小型的共享库,内核会自动将其映射到所有用户空间应用程序的地址空间中。应用程序通常无需关注这些细节,因为vDSO最常由C库调用。这样,可以以正常方式编码,使用标准函数,而C库会负责使用通过vDSO可用的任何功能。

vDSO的存在是为什么?内核提供了一些系统调用,用户空间代码经常使用这些调用,以至于这些调用可能主导整体性能。这既是由于调用的频率,又是由于从用户空间退出并进入内核所产生的上下文切换开销。

vdso包含一组特定的函数,这些函数在用户空间中执行,但其实现是由内核提供的。用户空间程序可以通过调用这些函数来访问一些系统功能,而无需陷入内核态。

vdso的一个重要用途是实现系统调用的快速路径。当用户空间程序执行系统调用时,通常需要进行一次上下文切换,将控制权从用户态切换到内核态。然而,某些系统调用是非常频繁且开销较小的,这种上下文切换的开销可能会成为性能瓶颈。vdso提供了一个快速路径,通过在用户空间中执行特定的系统调用函数,避免了不必要的上下文切换,从而提高了系统调用的性能。

在Linux中,vdso通常以linux-vdso.so.X的形式存在于/proc/self/maps中,并且被映射到每个进程的地址空间中。这样,用户空间程序可以直接调用vdso中的函数,而无需显式加载和链接vdso库。

总结来说,vdso是Linux中用于优化系统调用性能的一种机制,它提供了一组在用户空间执行的特定系统调用函数,以减少用户态和内核态之间的上下文切换开销,并提高系统性能。

备注:
vdso只包括了几个特定的系统调用:

clock_gettime
gettimeofday
getcpu
time
clock_getres

比如gettimeofday:
一个经常被使用的系统调用是gettimeofday(2)。这个系统调用既可以被用户空间应用程序直接调用,也可以被C库间接调用。想象一下时间戳、定时循环或轮询,所有这些都经常需要知道当前的时间。这些信息也不是机密的,任何特权模式(root或非特权用户)的应用程序都会得到相同的答案。因此,内核会安排将回答这个问题所需的信息放置在进程可以访问的内存中。现在,调用gettimeofday(2)变成了一个普通的函数调用和几次内存访问。

二、vdso

2.1 用户态

# ldd /usr/bin/lslinux-vdso.so.1 (0x00007ffca7b40000)......
# cat /proc/1/maps
55637a23d000-55637a26f000 r--p 00000000 08:05 59514907                   /usr/lib/systemd/systemd
55637a26f000-55637a32d000 r-xp 00032000 08:05 59514907                   /usr/lib/systemd/systemd
55637a32d000-55637a383000 r--p 000f0000 08:05 59514907                   /usr/lib/systemd/systemd
55637a383000-55637a3c9000 r--p 00145000 08:05 59514907                   /usr/lib/systemd/systemd
55637a3c9000-55637a3ca000 rw-p 0018b000 08:05 59514907                   /usr/lib/systemd/systemd
55637c14a000-55637c416000 rw-p 00000000 00:00 0                          [heap]......7f008b2bf000-7f008b2c0000 rw-p 00000000 00:00 0
7ffd3bc40000-7ffd3bd42000 rw-p 00000000 00:00 0                          [stack]
7ffd3bd4f000-7ffd3bd53000 r--p 00000000 00:00 0                          [vvar]
7ffd3bd53000-7ffd3bd55000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

其中:

7ffd3bd53000-7ffd3bd55000 r-xp 00000000 00:00 0                          [vdso]

可以看到vdso内存大小:0x2000 = 4096 * 2,即两个虚拟页面的大小。

vdso的起始虚拟地址在进程1是:0x7ffd3bd53000,转化为十进制即140725607280640,将这段内存dump到文件中:

# dd if=/proc/1/mem of=/tmp/linux-vdso.so skip=140725607280640 ibs=1 count=8192
dd: /proc/1/mem: cannot skip to specified offset
8192+0 records in
16+0 records out
8192 bytes (8.2 kB, 8.0 KiB) copied, 0.00971912 s, 843 kB/s

由于vDSO是一个完整的ELF镜像,可以对其进行符号查找:

# objdump -T /tmp/linux-vdso.so/tmp/linux-vdso.so:     file format elf64-x86-64DYNAMIC SYMBOL TABLE:
0000000000000a10  w   DF .text  0000000000000413  LINUX_2.6   clock_gettime
0000000000000690 g    DF .text  0000000000000348  LINUX_2.6   __vdso_gettimeofday
0000000000000e30  w   DF .text  0000000000000060  LINUX_2.6   clock_getres
0000000000000e30 g    DF .text  0000000000000060  LINUX_2.6   __vdso_clock_getres
0000000000000690  w   DF .text  0000000000000348  LINUX_2.6   gettimeofday
00000000000009e0 g    DF .text  0000000000000029  LINUX_2.6   __vdso_time
0000000000000ec0 g    DF .text  000000000000009c  LINUX_2.6   __vdso_sgx_enter_enclave
00000000000009e0  w   DF .text  0000000000000029  LINUX_2.6   time
0000000000000a10 g    DF .text  0000000000000413  LINUX_2.6   __vdso_clock_gettime
0000000000000000 g    DO *ABS*  0000000000000000  LINUX_2.6   LINUX_2.6
0000000000000e90 g    DF .text  0000000000000025  LINUX_2.6   __vdso_getcpu
0000000000000e90  w   DF .text  0000000000000025  LINUX_2.6   getcp

2.2 内核态

vDSO 会向用户提供的 syscall:

// linux-5.13/arch/x86/entry/vdso/vdso.lds.S/** This controls what userland symbols we export from the vDSO.*/
VERSION {LINUX_2.6 {global:clock_gettime;__vdso_clock_gettime;gettimeofday;__vdso_gettimeofday;getcpu;__vdso_getcpu;time;__vdso_time;clock_getres;__vdso_clock_getres;__vdso_sgx_enter_enclave;local: *;};
}

即:

__vdso_clock_gettime
__vdso_gettimeofday
__vdso_getcpu
__vdso_time
__vdso_clock_getres
__vdso_sgx_enter_enclave

通常,vDSO遵循将所有符号以“_vdso”或“_kernel”作为前缀的命名约定,以便将它们与其他标准符号区分开。例如,“gettimeofday”函数的名称是“__vdso_gettimeofday”。

可以看到用户态vdso虚拟地址内容一样。

2.3 内核源码解析

内核具体源码解析请参考:
https://tinylab.org/riscv-syscall-part4-vdso-implementation/
https://www.bookstack.cn/read/linux-insides-zh/SysCall-linux-syscall-3.md
https://zhuanlan.zhihu.com/p/611286101

参考资料

Linux 5.13
https://man7.org/linux/man-pages/man7/vdso.7.html
https://blog.rustforever.top/2022/02/10/linux/syscall/vdso/
https://zhuanlan.zhihu.com/p/620578643
https://cloud.tencent.com/developer/article/1517837

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218491.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个例子带你入门影刀编码版(二)

文章结构 摘要元素定位店铺所有宝贝单个宝贝详细信息相关链接 摘要 将通过一个电商业务场景下的真实需求,带领大家零基础入门影刀编码版,本系列将会分三步讲解,从接到需求到最后完成发版,整个过程中我们需要做些什么?…

滑动窗口最大值和前K个高频元素

滑动窗口最大值和前K个高频元素 239. 滑动窗口最大值 核心:建立一个单调队列,维护里面的最大值,并且从大到小的顺序即可!【只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。…

BugKu-Web-Simple_SSTI_1Simple_SSTI_2(浅析SSTI模板注入!)

何为SSTI模块注入? SSTI即服务器端模板注入(Server-Side Template Injection),是一种注入漏洞。 服务端接收了用户的恶意输入以后,未经任何处理就将其作为Web应用模板内容的一部分,模板引擎在进行目标编译渲…

深入理解TheadLocal的使用场景和注意事项

前言 在日常实际开发当中我们往往会看到项目中有使用 ThreadLocal 的场景,大多数人有时候可能涉及不到自己的业务则没有进行关注。通常我在看代码时对于一些未知的东西常常引起我的好奇,我往往会分析:为什么要这么做?好处是什么&…

uniapp todo list

uniapp github 开源项目推荐系统 github-掘金

SQL基础理论篇(十二):游标

文章目录 简介什么是游标如何使用游标参考文献 简介 sql编程与传统编程最大的区别之一,就是sql是面向集合的思考方式,更加关注“获取什么”,而不是如何获取。因为sql本身是以关系模型和集合论作为基础的。 在有的情况下,我们不需…

fuxploide,一款针对文件上传的Fuzz检测工具

fuxploide,一款针对文件上传的Fuzz检测工具 1.工具概述2.安装3.参数解析4.使用案例1.工具概述 Fuxploider 是一种开源渗透测试工具,可自动检测和利用文件上传表单缺陷。该工具能够检测允许上传的文件类型,并能够检测哪种技术最适合在所需的 Web 服务器上上传 Web Shell 或任…

【ARM Trace32(劳特巴赫) 使用介绍 1.2 - ARM 系统调试中常见的挑战】

请阅读【Trace32 ARM 专栏导读】 文章目录 ARM 系统调试中常见的挑战ARM 系统调试接口简例DAP-Debug Access portDAP 状态检查多核调试虚拟/物理地址Cache 数据一致性问题系统异常系统复位系统死机PC 采样Memory 采样RAM/Core Dump 分析小概率问题ARM 系统调试中常见的挑战 调试…

交直流充电桩检测

随着电动汽车的普及,充电桩的需求也在不断增加。为了保证充电桩的正常运行和使用安全,对其进行定期检测是非常必要的。检查充电桩的外壳是否有破损、变形等现象,以及充电桩的标识是否清晰可见。同时,还要检查充电桩的接口是否完好…

图像融合——现有比较火的网络

在深度学习中,用于图像融合的详细网络(深度神经网络)通常是为了学习如何结合来自多个源的信息以生成一个单一、增强的输出图像。这些网络可以基于不同的架构设计,下面是一些常用于图像融合任务的深度学习网络类型: 卷积…

Elasticsearch:使用 OpenAI 生成嵌入并进行向量搜索 - nodejs

在我之前的文章: Elasticsearch:使用 Open AI 和 Langchain 的 RAG - Retrieval Augmented Generation (一)(二)(三)(四)​​​​​ 我详细地描述了如何使用…

自然语言处理第2天:自然语言处理词语编码

​ ☁️主页 Nowl 🔥专栏 《自然语言处理》 📑君子坐而论道,少年起而行之 ​​ 文章目录 一、自然语言处理介绍二、常见的词编码方式1.one-hot介绍缺点 2.词嵌入介绍说明 三、代码演示四、结语 一、自然语言处理介绍 自然语言处理&#xf…

短视频时代,不直播带货怎么获得一手流量?

我是电商珠珠 短视频的出现改变了每个人的娱乐方式,国内的三大巨头:快手、视频号、抖音,这三个的市场定位也有着一定的区别。 快手最早成立于12年11月,面对的用户比较广,整体定位三四线城市,男女均衡。其…

5、Grounded Segement Anything

github sam安装与基本使用 stable diffusion安装与基本使用 安装GroundingDINO git clone https://github.com/IDEA-Research/GroundingDINO.git cd GroundingDINO pip install -e .pip install diffusers transformers accelerate scipy safetensors安装RAM&Tag2Text …

深度学习基本概念

1.全连接层 全连接层就是该层的所有节点与输入节点全部相连,如图所 示。假设输入节点为X1, X 2, X 3,输出节点为 Y 1, Y 2, Y 3, Y 4。令 矩阵 W 代表全连接层的权重, W 12也就代表 …

【C】⽂件操作

1. 为什么使⽤⽂件? 如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化…

世微 AP5199S 降压恒流车灯驱动IC 兼容HV9910

说明 AP5199S 是一款外围电路简单的多功能平均电流 型 LED 恒流驱动器,适用于宽电压范围的非隔离式 大功率恒流 LED 驱动领域。 芯片 PWM 端口支持超小占空比的 PWM 调光, 可响应最小 60ns 脉宽。芯片采用我司专利算法,为客 户提供最佳解决方…

AIGC时代,如何保障ai绘图的算力需求

AIGC是目前非常热门的技术领域,被广泛应用于各个行业和领域,但同时AIGC也面临着诸多的痛点,那么如何解决这些痛点问题呢?云时代,又是如何通过云电脑赋能AIGC行业的,那么一起来文章中了解一下吧。 AIGC是什…

Trie 树详解

Trie 树详解 Trie 树(字典树)是一种用于高效存储和搜索字符串集合的树状数据结构。它的主要特点是能够在O(N)时间内实现字符串的插入、删除和搜索操作,其中 N 是字符串的长度。Trie 树的结构适用于敏感词过滤、单词搜索、自动补全等场景。在…

【HarmonyOS】【DevEco Studio】安装教程及环境配置问题解决

目录 一、DevEco Studio 安装二、配置环境ohmp安装报错问题解决方法一:注册表删除数值(没解决)方法二:进入DevEco Studio点击Settings进入设置(没解决)方法三:自己去官网下载ohmp的包安装&#…