是一种在软件开发过程中常用的技术,用于在编译时将变量的内存地址与其名称进行映射。这种映射可以在运行时通过变量名称来访问和修改变量的值,而不需要直接操作内存地址。
优势:
应用场景:
推荐的腾讯云相关产品:
腾讯云提供了一系列与云计算相关的产品和服务,以下是一些推荐的产品:
腾讯云产品介绍链接地址:
1、问题背景在Python中,我们可以使用装饰器来修改函数或方法的行为,但当装饰器需要使用一个在实例化时创建的对象时,事情就会变得复杂。...例如,我们想要创建一个装饰器,可以创建一个新的函数/方法来使用对象obj。如果被装饰的对象是一个函数,那么obj必须在函数创建时被实例化。...请注意,这种解决方案只适用于对象obj在实例化时创建的情况。如果obj需要在其他时间创建,那么您需要修改此解决方案以适应您的具体情况。
文章目录 一、mmap 创建内存映射代码示例 1、fopen 打开或创建文件 2、lseek 设置文件大小 3、mmap 函数使用 4、munmap 删除内存映射 二、完整代码示例 一、mmap 创建内存映射代码示例...fd : 文件描述符 , 被映射的文件 0 : 被映射文件的偏移量 , 从文件的哪个字节位置开始映射 如果返回 -1 指针 , 则说明 内存映射 创建失败 ; // 创建文件映射 //...文件映射创建失败 !")...printf("mmap 文件映射创建失败 !")..., 编译上述源码 , 并输出可执行文件 mmap_demo_01 , 执行 .
然而,单纯的将程序所占虚拟地址空间直接映射到物理内存无法解决内存使用效率低的问题,物理内存仍然会快速消耗殆尽。 页映射机制 程序局部性原理:一个程序在运行时,某段时间内只使用到了一部分程序数据。...可执行文件的装载 根据前面分析的页映射机制,可执行文件装载进内存需要两个映射关系: 虚拟空间 : 物理内存 虚拟空间 : 可执行文件 创建一个进程,或者说创建一个虚拟空间,第一步是操作系统创建一个页目录...第二步是建立虚拟空间与可执行文件的映射关系。前面已经分析过了,可执行文件的 程序头表 已经包含了每一个 Segment 的虚拟地址、在文件中的偏移。...减少编译和静态链接的时间消耗,降低可执行文件所占磁盘空间。 共享对象的更新和发布更便捷,可执行文件一般不用重新编译链接。 通过共享对象来做复杂的系统兼容,增强可执行文件的兼容性。...处理方式是,在数据段里面建立一个指向这些变量的指针数组,这个指针数组称作 全局偏移表 (Global Offset Table, GOT) 。
| munmap 删除内存映射 ) 中 , 完成了 进程一 的程序 , 在该进程中 , 创建并打开文件 , 为该文件设置大小 , 使用 mmap 创建 " 文件映射 " , 并通过直接访问内存的方式..., 为该文件设置数据 ; 数据设置完毕后 , 休眠 8 秒 , 在这段休眠的时间段 , 运行 进程二 , 在 进程二中 , 创建相同文件的 mmap " 文件映射 " , 读取在 进程一 中写入的文件内容...// MAP_SHARED : 指定映射关系 , 指的是该映射是进程的共享内存空间 // fd : 文件描述符 , 被映射的文件 // 0 : 被映射文件的偏移量 , 从文件的哪个字节位置开始映射...\n"); return 0; } 上述源码 , 放在 mmap_demo_02.c 文件中 , 执行 gcc mmap_demo_02.c -o mmap_demo_02 命令 , 编译该源码..., 编译出的可执行文件为 mmap_demo_02 ; 三、mmap 进程共享内存展示 ---- 先执行 进程一 mmap_demo_01 可执行程序 , 进程一 中通过 mmap 文件映射向文件中写出数据后
每当你调用一个新函数时,它都会为该函数的局部变量创建一个新的堆栈框架。...我们对解析器堆栈框架做了一个小更改,即在 Sparkplug 代码执行期间,我们不让字节码偏移保持最新。相反,我们存储一个从 Sparkplug 代码地址范围到对应的字节码偏移量的双向映射。...每当一个堆栈框架访问想要知道一个 Sparkplug 框架的“字节码偏移量”时,我们都会在此映射中查找当前执行的指令,并返回相应的字节码偏移量。...类似地,每当我们想将 OSR 从解析器转换为 Sparkplug 时,我们都可以在映射中查找当前字节码偏移量,然后跳转到相应的 Sparkplug 指令。...在这些基准测试上,我们选择查看“V8 主线程时间”指标,其测试主线程(不包括流解析或后台优化的编译)在 V8 中花费的总时间(包括编译和执行)。
时间 可以通过 stat 查看指定文件的 ACM 时间信息 这三个时间的刷新策略如下: Access:最近一次查看内容的时间,具体实现取决于系统 Change:最近一次修改属性的时间 Modify...环境变量 LD_LIBRARY_PATH (默认没有这个环境变量),将第三方动态库路径添加至此环境变量中(临时方案) sudo 在 /lib64/ 目录下建立动态库的软链接 更改配置文件 /etc/ld.so.conf.d...:通过环境变量解决 添加动态库路径至 LD_LIBRARY_PATH 环境变量中 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/Yohifo/linux/Explore...;动态链接采用 相对地址 的方式进行链接,同一个函数的 动态库起始地址 + 所链接函数偏移量 值相同,代码只需要加载一份,并且可以任意位置进行函数调用(与位置无关) 动态库中所有地址都是偏移量,默认从...0 开始 只有当一个库被真正映射进地址空间后,它的起始地址才能真正确定 链接库中的函数时,通过 动态库的起始地址 + 函数偏移量 的方式链接函数 这种方法不论在什么位置,都可以随便链接函数(与位置无关
符号解析与重定位 编译器在将”a.c”编译成指令时,它如何访问”shared”变量?如何调用”swap”函数?...进程的建立需要做下面三件事情: 创建一个独立的虚拟地址空间 读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系。 将CPU的指令寄存器设置成可执行文件的入口地址,启动运行。...例如下图中,操作系统创建进程后,会在进程相应的数据结构中设置有一个.text段的VMA:它在虚拟空间中的地址为0x08048000~0x08049000,它对应ELF文件中偏移为0的.text,它的属性为只读...CPU将控制权交给操作系统,操作系统将查询虚拟空间与可执行文件的映射关系表,找到空页面所在的VMA,计算相应的页面在可执行文件中的偏移,然后在物理内存中分配一个物理页面,将进程中该虚拟页与分配的物理页之间建立映射关系...全局偏移表(GOT) 用于模块间数据访问,在数据段里建立一个指向外部模块变量的指针数组。当代码需要引用该全局变量时,可以通过GOT中相对用的项间接引用,它的基本机制如下图。 ?
若这些数据不需要CPU处理,则浪费了大量的CPU时间。如果在主存和辅存之间之间开辟一条数据通路,则可提高CPU的使用率,同时可以加快主存和辅存之间交换数据的速度,进而提高整机的性能。...(2)ZONE_NORMAL (3)ZONE_HEIGHMEM:主要用于在32bit的linux系统中在内核映射高于1GB的物理内存时会用到高端内存。 四、深入编译和链接过程。...合并所有.obj文件的段,调整段大小和段偏移,重点:合并符号表,进行符号解析,即符号的重定位,即在符号引用的地方找到符号定义的地方。.../a.out 创建虚拟地址空间到物理内存的映射(创建内核地址映射结构体),创建页目录和页表。 (2)加载代码段和数据段。...而从磁盘到虚拟地址空间的映射是由mmap函数的映射,而虚拟地址空间到物理内存映射是多级页表的方式进行映射的,属于操作系统的内容。关于多级页表映射方式我会独立写出一篇相关的博客。 strace .
/mylib/lib -lmyc 使用命令直接表明使用的头文件路径,库文件路径和使用的库 动态库: 直接安装到系统中/lib64/(或者建立软连接) 命令行修改环境变量 修改环境变量初始化脚本文件...动态库也会写入到内存中,并通过页表映射到地址空间中的共享区。让调用的时候通过共享区来找到对应的方法实现。 其他的可执行文件相要调用动态库中的方法是,也可以通过页表来映射就可以。...总结一下: 进程创建阶段,初始化地址空间,让CPU知道main函数的入口地址 加载 -> 每一行代码与数据就都有了物理地址,自己的虚拟地址自己也就知道了,就可以构建映射了 接下来我们就来看看动态库是如何加载的...+ 偏移量找到对应的函数就可以执行了。...同样其他进程也可以通过共享区的库的起始地址 + 偏移量映射,来访问内存中的函数。库函数调用,其实也是在进程的地址空间里来回跳转!!!与非库函数类似奥! 那么怎么知道一个库有没有被加载到内存中呢?
接下来我们在该目录下创建一个测试以上方法的主函数 TestMain.c: 假设现在我们需要将上面的所有文件形成一个可执行程序测试,该如何编译呢?使用 gcc!...所以我们先创建一个 Makefile,进行对上面的实践: 如上图,我们解释一下各项的作用。...接下来我们导一下环境变量,再查看 LD_LIBRART_PATH 下的环境变量就可以找到了: 添加之后是即时生效的,这时候系统就知道我们的库的路径了: 接下来我们的可执行程序也就可以执行了: 但是当前这种方法导环境变量是内存级的...当我们的程序编译成为二进制文件之后,变量名、函数名等,还有吗?没有了!编译的时候,对代码进行编址,基本遵守虚拟地址空间那一套!...虚拟地址空间不仅仅是操作系统里面的概念,编译器编译的时候,也要按照这样的规则编译可执行程序,这样才能在加载的时候,进行从磁盘文件到内存,再进行映射。
2、将库路径导入环境变量LD_LIBRARY_PATH中 用export指令,将库路径(绝对路径)导入环境变量LD_LIBRARY_PATH中,如下: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH...,因为下次重新登陆时,该环境变量会被更新。...而动态链接则不是这样,程序在链接动态库时,会通过库的起始地址+偏移量,来找到函数方法所在的位置,而这个偏移量,就是我们生成的与位置无关码。...因为库被映射到地址空间的地址是不确定的,但是偏移量是固定的,这样不管库被映射到哪个地址,通过偏移量都可以找到函数所在的位置。...同时假如存在多个进程同时运行且使用同一个库,那么动态库也只需要在内存中加载一份,然后映射到各自的共享区,通过库地址+偏移量就可以跳转到方法的实现。大大节省了空间的使用。
由此可知,new一个对象需要四条字节码指令,先创建对象存放在栈顶,然后将栈顶存放的对象复制一份,用于调用类的实例初始化方法,最后还是将new指令创建出来的那份赋值给局部变量或者字段。...1、偏移量为8的字节码指令是aload_1,该指令将局部变量表索引为1的元素放到操作数栈顶,即将第一部分字节码创建出来的UserService对象的引用放入操作数栈顶。...偏移量为0的aload_0指令是将this引用放入操作数栈栈顶。此时操作数栈的变化如图 ? 偏移量为1、4、5三条指令是创建一个UserDao对象,这三条指令执行完成后,操作数栈顶的变化如图 ?...实例初始化方法 实例初始化方法是在创建对象之后调用的,Java代码中使用new关键字创建一个对象,编译成字节码后是通过两条指令来完成的,第一条是new指令,第二条是方法调用指令,即调用类的实例初始化方法...第一个字节0xAB是lookupswitch指令的操作码,接着后面四个字节也是匹配default时跳转的目标指令相对当前指令的偏移量,紧随其后四个字节0x00000002代表后面跟随多少个条件映射,每八个字节为一个条件映射
号之间的映射关系 硬链接本质就是在指定的目录下,插入新的文件名和目标文件的映射关系,并让inode的引用计数++ 创建硬链接:要创建硬链接,可以使用ln命令,语法如下: ln <link_name...如果某个目标文件不存在,或者某个依赖文件的时间戳比目标文件的时间戳更新,那么 Make 工具会执行该规则中定义的命令来生成目标文件。...通过设置 LD_LIBRARY_PATH 环境变量,您可以告诉系统在哪些路径中查找动态链接库。这个环境变量在编译和运行需要动态链接库的程序时非常有用。...在编译过程中,编译器会为程序中的各个变量、函数等符号分配地址,这些地址通常是相对地址或者符号表中的偏移量。这样,即使程序还没有被加载到内存中,各个符号仍然具有自己的地址。...这些地址和区域的信息在程序加载到内存时会被操作系统读取,并根据这些信息将程序的各个部分映射到进程的虚拟地址空间中。 所以,我们之前讲解的进程地址空间里的虚拟地址,其实是由编译器在编译过程生成的。
,首先要明确的是 cahce 缓存的单位是缓存行,对应主存中的一个内存块,并不是一个变量,这个主要是因为 ** CPU 访问的空间局限性:被访问的某个存储单元,在一个较短时间内,很有可能再次被访问到,以及空间局限性...而将汇编指令转换成机器指令由硬件直接实现,这一步速度是很快的,当然 JVM 为了提高运行效率也可以将某些热点代码(一个方法内的代码)一次全部编译成机器指令后然后在执行,也就是和解释执行对应的即时编译(JIT...例如执行系统调用创建线程的指令,而 CPU 每执行完一个指令,就会检查中断寄存器中是否有中断,如果有就取出然后执行该中断对应的处理程序。...,而且这个地址需要在编译的时候就要确认。...下面我们贴一段 rocketmq 消息存储模块的代码,位于 MappedFile 类中,这个类是 rocketMq 消息存储的核心类感兴趣的可以自行研究,下面两个方法一个是创建文件映射,一个是预热文件,
程序到运行主要经过程序(外存)编译,链接,装入(内存)。...2) 数据段:存放已初始化的全局变量,静态变量(包括全局和局部的),常量。static全局变量和static函数只能在当前文件中被调用。 ...4) 栈区:由编译器自动释放,存放函数的参数值,局部变量等。每当一个函数被调用时,该函数的返回类型和一些调用的信息被存储到栈中。然后这个被调用的函数再为它的自动变量和临时变量在栈上分配空间。...很简单,逻辑地址就是你源程序里使用的地址,或者源代码经过编译以后编译器将一些标号,变量转换成的地址,或者相对于当前段的偏移地址。 逻辑地址是指由程序产生的与段相关的偏移地址部分。...2)、最近最久未使用(LRU)置换算法 选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问。
,首先要明确的是 cahce 缓存的单位是缓存行,对应主存中的一个内存块,并不是一个变量,这个主要是因为 ** CPU 访问的空间局限性:被访问的某个存储单元,在一个较短时间内,很有可能再次被访问到,以及空间局限性...假设我们现在还没有虚拟地址,只有物理地址,编译器在编译程序的时候,需要将高级语言转换成机器指令,那么 CPU 访问内存的时候必须指定一个地址,这个地址如果是一个绝对的物理地址,那么程序就必须放在内存中的一个固定的地方...,而且这个地址需要在编译的时候就要确认....下面我们贴一段 rocketmq 消息存储模块的代码,位于 MappedFile 类中,这个类是 rocketMq 消息存储的核心类感兴趣的可以自行研究,下面两个方法一个是创建文件映射,一个是预热文件,...那么属性的偏移量具体根据什么规则来确定的呢?
、静态变量、指针,引用、文件等,而独自占有栈 3、一个进程可以创建多少线程,和什么有关?...理论上,一个进程可用虚拟空间是2G,默认情况下,线程的栈的大小是1MB,所以理论上最多只能创建2048个线程。如果要创建多于2048的话,必须修改编译器的设置。...共享内存:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的IPC方式,它是针对其他进程间通信方式运行效率低而专门设计的。...在使用静态库的情况下,在编译链接可执行文件时,链接器从库 中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件。...其次内存共享的速度也比较快,不存在读取文件、消息传递等过程,只需要到相应映射到的内存地址直接读写数据即可。 信号量 在提到共享内存方式时也提到,进程共享内存和多线程共享全局变量非常相似。
点击上方“嵌入式与Linux那些事”,选择“置顶/星标公众号” 福利干货,第一时间送达 ARM32位系统的内存布局图 32位操作系统的内存布局很经典,很多书籍都是以32位系统为例子去讲解的。...这里讲的线性映射就是直接把物理内存的地址映射到线性映射区中,假设物理内存的DDR起始地址是0,映射的时候就有一个偏移量,这个偏移量就是0XC0000000,page offset。....text:代码段,程序编译完后的机器指令。 .data:初始化过的全局的静态变量,还有一些局部的静态变量。 .rodata:只读变量,字符串,常量等。....bss:未初始化的全局变量以及初始化为零的变量。 readelf 查看程序头 使用-l参数读下程序头(program header),它是用来描述OS是如何被映射到进程的虚拟地址空间的。...偏移地址:即本段映射地址在文件中的偏移;对于有名映射指本段映射地址在文件中的偏移,对应vm_pgoff;对于匿名映射为vm_area_struct->vm_start。
它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。...当然这些信息中,有些信息(如本地变量表、指令和代码行偏移量映射表、常量池中方法的参数名称等等)需要在使用javac编译成class文件时,指定参数才能输出,比如,你直接javac xx.java,就不会在生成对应的局部变量表等信息...如果你使用的eclipse,则默认情况下,eclipse在编译时会帮你生成局部变量表、指令和代码行偏移量映射表等信息的。 通过反编译生成的汇编代码,我们可以深入的了解java代码的工作机制。...二、javap测试及内容详解 前面已经介绍过javap输出的内容有哪些,东西比较多,这里主要介绍其中code区(汇编指令)、局部变量表和代码行偏移映射三个部分。...,start+length表示这个变量在字节码中的生命周期起始和结束的偏移位置(this生命周期从头0到结尾10),slot就是这个变量在局部变量表中的槽位(槽位可复用),name就是变量名称,Signatur
,首先要明确的是 cahce 缓存的单位是缓存行,对应主存中的一个内存块,并不是一个变量,这个主要是因为 CPU 访问的空间局限性:被访问的某个存储单元,在一个较短时间内,很有可能再次被访问到,以及空间局限性...在程序设计的时候我们要尽量减少用户态到内核态的切换,例如创建线程是一个系统调用,所以我们有了线程池的实现。...,存入操作系统的内核缓冲区,然后在从内核缓冲区拷贝到用户空间,而内存映射,是将磁盘文件直接映射到用户的虚拟存储空间中,通过页表维护虚拟地址到磁盘的映射,通过内存映射的方式读取文件的好处有,因为减少了从内核缓冲区到用户空间的拷贝...下面我们贴一段 rocketmq 消息存储模块的代码,位于 MappedFile 类中,这个类是 rocketMq 消息存储的核心类感兴趣的可以自行研究,下面两个方法一个是创建文件映射,一个是预热文件,...,当然由于直接使用内核线程,所以能够创建的最大线程数也受内核控制。
领取专属 10元无门槛券
手把手带您无忧上云