珠海做网站最好的公司网吧服务员

pingmian/2025/10/9 22:51:05/文章来源:
珠海做网站最好的公司,网吧服务员,网站建设模板一次收费,如何改进网站绪论 大家好#xff0c;欢迎来到【程序员的自我修养】专栏。正如其专栏名#xff0c;本专栏主要分享学习《程序员的自我修养——链接、装载与库》的知识点以及结合自己的工作经验以及思考。编译原理相关知识本身就比较有难度#xff0c;我会尽自己最大的努力#xff0c;争… 绪论 大家好欢迎来到【程序员的自我修养】专栏。正如其专栏名本专栏主要分享学习《程序员的自我修养——链接、装载与库》的知识点以及结合自己的工作经验以及思考。编译原理相关知识本身就比较有难度我会尽自己最大的努力争取深入浅出。若你希望与一群志同道合的朋友一起学习也希望加入到我们的学习群中。文末有加入方式。 介绍 通过前文的讲解我们大致了解将程序加载到内存的过程。即创建两个映射表程序与虚拟内存空间映射表、虚拟内存空间与物理内存映射表。之后在程序运行过程中通过不断触发页错误持续将相应程序页加载到内存中从而保证进程正常运行。似乎一切都已经完备了。的确在早期的程序开发中源文件经过编译生成可重定位文件.o文件再经过静态链接生成可执行的ELF文件最终运行时通过页加载和页错误的方式保证进程的正常运行。已经能够满足当时程序的研发大家开发和使用都非常方便。 但是随着IT行业的发展原先静态链接方式的缺点也逐渐显露。比如 由于业务越来越复杂导致程序的体积也越来越大在多进程的操作系统中可能同时存在成百上千各应用同时运行。每个应用中都会使用到printf、scanf、strlen等基础函数那么不同的程序中一定会包含它们的指令部分。这就导致这些程序在磁盘保存时都有这些基础函数的副本。运行时也会将这些副本加载到对应进程的虚拟空间内存中去。这就导致了浪费磁盘和内存。如下 特别是Android开发行业APP的更新周期非常快导致原有的方式非常麻烦。比如上面的举例中由于多个应用使用了printf接口模块若发现其中有bug就需要用新版本的printf.o与当前的其它文件进行重新编译、链接再将编译好的程序进行在线更新。这就导致错误的printf.o模块可能只有1KB大小,但是用户最终需要将整个程序可能会有10MB下载进行更新。这在以往流量收费的背景下是非常不人性化的。 在上述两个核心问题的背景下前人们就开始思考如何解决这样的难题。最终的解决方案就是我们现在熟悉的动态库其核心思想就是把程序按照模块拆分成各个相对独立部分在程序运行时才将它们链接在一起形成一个完成的程序而不是像静态链接一样把所有的程序模块都链接成一个单独的可执行程序。如下 接下来我们开始学习如何实现这一功能。内容会比较多我会尽自己最大努力做到深入浅出若由任何意见、问题都欢迎在评论区指出。让我们一起坚持下去。 动态链接 我们看一个最简单的动态库使用案例。 //main.c extern void func(int i);int main() {func(5);return 0; }//func.c #includestdio.h void func(int i) {printf(input i %d\n,i);return; }编译 gcc -shared -fPIC -o libfunc.so fun.c gcc main.c -o main -L./ -lfunc运行 yihuaubuntu:~/test/dynamic-relocate$ export LD_LIBRARY_PATH./ yihuaubuntu:~/test/dynamic-relocate$ ./main input i 5 yihuaubuntu:~/test/dynamic-relocate$通过【程序员的自我修养05】符号修正的功臣——重定位表内容可知若是静态链接此时main进程中对func的引用是绝对地址。 但是main.o生成main程序时如何知道func符号的类型呢即该符号是静态符号还是动态符号呢 若是静态符号则在链接阶段将其加载到程序中并将main函数中的引用进行重定位若是动态符号则等到运行时再重定位。 其实就是通过编译参数中-lfunc确定。因为libfunc.so的符号表中有func,当链接器发现该符号存在于.so中则将其作为动态符号处理。这也说明了为什么静态链接阶段我们还需要动态库的原因。静态链接阶段动态库的作用就是用于区别符号的类型。 完成第一步链接阶段确定符号的类型。 当我们运行程序时libfunc.so加载到内存中其代码段的虚拟地址也就确定了。那么再修改所有引用到func符号的地址。就可以完成main-func的引用。如下 完成第二步运行时重定位。 到了这里我们似乎好像已经实现了动态链接过程了。但是我们仔细观察上图的流程我们会发现重定位阶段会对代码段进行重定位修改函数地址并且不同的库在不同的进程加载地址可能是不同的。这就导致上述流程中动态库中的代码段在多个进程中无法实现共享也就无法解决浪费内存的问题。 地址无关代码 为了解决装载时重定位导致动态库指令部分无法在多个进程之间共享的问题。伟大的前辈们想到了一个思路:把动态库中的指令中那些需要被修改的部分分离出来跟数据部分放在一起这样指令部分可以保持不变而数据部分可以在每个进程中拥有一个副本。而这个副本就是我们常见的GOTGlobal Offset Table表。 这样的思路似乎是可行的我们一起看看如何去实现。按照共享模块对象中的引用分为是否在本模块以及函数引用或数据访问。我们可以分为四类。 模块内部的函数调用模块内部的数据访问模块外部的函数调用模块外部的数据访问 一、模块内的函数调用 由于是模块内部调用且都属于代码段因而它们之间的相对地址是固定的。比如下列代码段内容 000000000000064a main:64a: 55 push %rbp64b: 48 89 e5 mov %rsp,%rbp64e: bf 05 00 00 00 mov $0x5,%edi653: e8 07 00 00 00 callq 65f func658: b8 00 00 00 00 mov $0x0,%eax65d: 5d pop %rbp65e: c3 retq000000000000065f func:65f: 55 push %rbp660: 48 89 e5 mov %rsp,%rbp663: 48 83 ec 10 sub $0x10,%rsp667: 89 7d fc mov %edi,-0x4(%rbp)66a: 8b 45 fc mov -0x4(%rbp),%eax66d: 89 c6 mov %eax,%esi66f: 48 8d 3d 9e 00 00 00 lea 0x9e(%rip),%rdi # 714 _IO_stdin_used0x4676: b8 00 00 00 00 mov $0x0,%eax67b: e8 a0 fe ff ff callq 520 printfplt680: 90 nop681: c9 leaveq682: c3 retq683: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)68a: 00 00 0068d: 0f 1f 00 nopl (%rax)分析main函数调用了func,其中main反汇编中对func的引用为e8 07 00 00 00,其中e8表示后面4字节是目标地址相对于下一条指令的偏移。下一指令地址为0x658偏移0x00000007即访问0x6580x070x65f地址正好为func的地址。 二、模块内的数据访问 我们知道一个模块前面一般是若干页的代码紧跟若干页的数据这些页之间的相对位置是固定的。也就是说可以按照第一类的方式进行相对寻址。又是如何实现的呢我们以下面的示例举例。 //2.c #includestdio.h static int a; int main() {a 5;return 0; }编译gcc 2.c -o 2。 查看反汇编objdump -d 2其中main输出如下 00000000000005fa main:5fa: 55 push %rbp5fb: 48 89 e5 mov %rsp,%rbp5fe: c7 05 0c 0a 20 00 05 movl $0x5,0x200a0c(%rip) # 201014 a605: 00 00 00608: b8 00 00 00 00 mov $0x0,%eax60d: 5d pop %rbp60e: c3 retq60f: 90 nop查看符号表readelf -s 2,其中全局变量a的内容如下 yihuaubuntu:~/test/dynamic-relocate$ readelf -s 2 ... 34: 0000000000201014 4 OBJECT LOCAL DEFAULT 23 a ...我们可以发现变量a在文件中的偏移是0x201014而movl $0x5,0x200a0c(%rip)下一个指令地址为0x6080x200a0c0x608刚到为符号a的地址。 三、模块间的函数访问 模块间的函数访问比较麻烦因为模块间的相对地址只有在加载时才能确认因此一、二方式不再适合直接使用。ELF的做法是借鉴场景二在本模块的数据段中建立一个指向这些变量的指针数组即GOT全局偏移表。代码段不再直接引用外部函数而是直接指向本模块数据段中GOT数组中对应指针。当程序加载时再重新对GOT表进行重定位。实现跳转访问。实现流程大致如下 分析如上所示func函数中调用了printf函数我们知道printf定义在libc.so中。为了保证libfunc.so动态库中代码段的通用性将其对printf的引用改为对数据段printfgot的引用。此时就和模块内部数据访问一样了。最终运行时函数调用流程应该为func-printfgot-printf。 四、 模块间的数据访问 对于模块间的数据访问其实实现逻辑与上面模块间的函数调用一致。在此不在赘述。 综上所述动态库实现地址无光代码的方式如下 至此动态库为何能够实现节约磁盘、内存,方便版本迭代的原因我们已经明白。上述的流程实质上已经能够实现动态库的加载、运行流程。但与现在的动态库实现流程还有些差别那就是延迟绑定PLT。 PLT 延迟绑定 通过上面所描述的动态库通过GOT表实现了地址无关代码**。动态库加载时**需要对所有GOT表项进行重定位动态库运行时,接口的实际调用变为了func-printfgot-printf。这就导致动态库相对于静态链接的启动速度需要进行重定位、运行速度间接调用略低。 经过长时间的发展人们发现了一个现象进程运行时动态库GOT表中并不是所有的外部接口数据都会被访问如果在加载过程中就全部进行重定位就是一种浪费降低启动速度。于是采用了一种叫做延迟绑定的做法基本思想就是当函数第一次被用到时才进行绑定符号查找、重定位。那么ELF如何实现这一逻辑的呢我们一起来看看。 首先我们一起思考符号重定位需要哪些东西呢 实现符号查找、绑定的接口。其真实名字就是_dl_runtime_resolve该函数肯定需要入参起码要知道要找哪个符号修改哪个模块中的地址吧。 待查找的符号待修改的地址 有了以上的期待我们一起分析ELF是如何实现延迟绑定地。调用函数不再是通过GOT表直接调转而是之间增加了一层PLT表结构。其大致实现逻辑为 printfpltjmp *(printfgot)push npush moduleIDjump _dl_runtime_resolve分析 第一条指令直接跳转到GOT表中的对应表项。当然第一次访问时里面肯定是为空的因为在加载时并没有进行重定位。于是会继续往下运行。第二条指令往栈中push该符号在符号表中的下标。第三条指令往栈中push该动态库模块ID标识。第四条指令调用_dl_runtime_resolve接口进行符号重定位。此时通过指令二指令三再结合本模块的符号表重定位表。_dl_runtime_resolve是可以找到对应符号以及修改printfgot表项内容。此时printfgot表项中即为实际printf地址。之后再次访问printfplt时执行第一条指令 jmp *(printfgot),此时printfgot表项内容不为空则直接跳转到printfgot表项再间接访问printf。 示例分析 我们尝试执行objdump -d libfunc.so分析其汇编逻辑相关内容如下 Disassembly of section .plt:0000000000000500 .plt:500: ff 35 02 0b 20 00 pushq 0x200b02(%rip) # 201008 _GLOBAL_OFFSET_TABLE_0x8506: ff 25 04 0b 20 00 jmpq *0x200b04(%rip) # 201010 _GLOBAL_OFFSET_TABLE_0x1050c: 0f 1f 40 00 nopl 0x0(%rax)0000000000000510 printfplt:510: ff 25 02 0b 20 00 jmpq *0x200b02(%rip) # 201018 printfGLIBC_2.2.5516: 68 00 00 00 00 pushq $0x051b: e9 e0 ff ff ff jmpq 500 .plt000000000000060a add:60a: 55 push %rbp60b: 48 89 e5 mov %rsp,%rbp60e: 48 83 ec 10 sub $0x10,%rsp612: 89 7d fc mov %edi,-0x4(%rbp)615: 89 75 f8 mov %esi,-0x8(%rbp)618: 8b 55 fc mov -0x4(%rbp),%edx61b: 8b 45 f8 mov -0x8(%rbp),%eax61e: 01 d0 add %edx,%eax620: 89 c6 mov %eax,%esi622: 48 8d 3d 20 00 00 00 lea 0x20(%rip),%rdi # 649 _fini0x9629: b8 00 00 00 00 mov $0x0,%eax62e: e8 dd fe ff ff callq 510 printfplt633: 8b 55 fc mov -0x4(%rbp),%edx636: 8b 45 f8 mov -0x8(%rbp),%eax639: 01 d0 add %edx,%eax63b: c9 leaveq63c: c3 retq分析 add中不再是对printgot引用而是对printfplt引用。查看printfplt的汇编语句。 第一条指令跳转到GOT表中的printfgot项。第一次访问时由于没有重定位因此为默认值下一条指令地址即516。第二条指令往栈空间push 符号ID这里填入的是0。第三条指令跳转到.plt。 而.plt中有三条指令。 第一条指令pushq 0x200b02(%rip),往栈中push GOT表中的第二项内容模块ID。第二条指令jmpq *0x200b04(%rip)跳转到GOT表中的第三项内容_dl_runtime_resolve。进行符号的查找及其重定位。第三条指令nopl 0x0(%rax),空指令没有实际含义。 此时printfgot表项中已填充为真实虚拟地址执行调用。 整体而言与ELF原理类似。可参考下图。 总结 本章我们从静态链接出发发现随着IT行业的发展静态链接存在浪费磁盘内存版本更新麻烦等问题。于是引入了动态链接的概念。并且引出动态链接会面对的问题以及实际上是如何解决这些问题的。 还有一些特殊场景还没有介绍比如共享模块的全局变量问题、数据段如何做到地址无关性。以及运行时重定位过程中详细流程。后续文章我会进一步介绍这些概念还请关注不错过。 下篇文章我会进一步介绍这些概念还请关注不错过。 若我的内容对您有所帮助还请关注我的公众号。不定期分享干活,剖析案例也可以一起讨论分享。 我的宗旨 踩完您工作中的所有坑并分享给您让你的工作无bug人生尽是坦途。

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

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

相关文章

网站加关键词代码开发公司项目经理职责

目录 一、SQL语句 1.1SQL语言分类 1.2查看数据库信息 1.3登录到你想登录的库 1.4查看数据库中的表信息 1.5显示数据表的结构(字段) 1.5.1数据表的结构 1.5.2常用的数据类型: 二、关系型数据库的四种语言 2.1DDL:数据定义语言&am…

自行建网站 所需费用郑州软件开发外包

分享来源:微信号:java一日一条 要想了解Java动态代理,首先要了解什么叫做代理,熟悉设计模式的朋友一定知道在Gof总结的23种设计模式中,有一种叫做代理(Proxy)的对象结构型模式,动态代理中的代理&#xff0c…

珠海品牌网站建河南网站建设推广

" A flow of control within a process that consists of a PC, a register set and a stack space" 本章将介绍为单个运行进程提供的新抽象 —— 线程 (thread) 线程是 调度的一个基本单位(basic unit of CPU scheduling)一个单独的线程至…

重庆网站建站建设平台为什么要做手机网站

1. 前言入门篇我们已经成功运行hello.benchmarks.yml并输出测试结果,本篇我们就hello.benchmarks.yml、以及运行的shell脚本详细解读下其中的含义2. 剖析hello.benchmarks.yml2.1. job在hello.benchmarks.yml中我们定义了一个新的job: server,并指定了仓…

网站策划要遵循的原则淡水网站建设定制

SpringBoot经典之作 进入Spring Boot世界 准备开发环境搭建开发工具 基础 Spring Boot基础分层开发Web应用程序响应式编程 进阶 Spring Boot进阶用ORM操作SQL数据库接口架构风格——RESTful集成安全框架,实现安全认证和授权集成Redis,实现高并发集成R…

网站建设流程书籍做旅游攻略网站好

最近来个需求,要求给小程序的 modal 增加个关闭按钮,上网一查发现原来 2018 年就有人给出解决方案了,于是总结下微信小程序自定义组件的思路:一句话,用 wxml css实现和原生组件类似的样式和效果,之后用 JS…

河南省建设协会网站微信网站搭建教程

前言 最近在和其他软件联合做一个本地图片选择传输功能,为此希望图片能够有序的呈现在客户端,简单的实现了一下功能,通过Mvvm模式进行呈现,过程简单通俗,话不多说直接上图。 处理过程 前台代码 你只需要粘贴到你的前台…

专业做网站app的公司哪家好百度网盘做自已网站

一次加入一个节点到我们的最下生成树中。加入哪个&#xff1f;跟着下面的步骤走一遍你就会了。 1. 把第一个节点A添加进来 2. 看两条边<A,B>,<A,E>,一个长度是3&#xff0c;一个长度是4&#xff0c;把长度短的边的另一个节点添加进来&#xff0c;也就是B 3. 再看A,…

atheme wordpress整站优化与关键词排名

随机森林超参数的网格优化&#xff08;机器学习的精华–调参&#xff09; 随机森林各个参数对算法的影响 影响力参数⭐⭐⭐⭐⭐几乎总是具有巨大影响力n_estimators&#xff08;整体学习能力&#xff09;max_depth&#xff08;粗剪枝&#xff09;max_features&#xff08;随机…

seo网站开发html交易网站设计实例

使用timeit模块进行速度测试,使用profile模块进行性能统计,使用dis模块进行字节码反汇编.下面的脚本演示了如何使用模块.从输出中注意到的一件事是函数调用的数量会影响整体性能(当然,字节码指令的数量也是如此).希望,(以及更多实验)应该为您提供有关如何提高功能效率的足够线索…

站酷网站的比赛网页谁做的上海网站推广定制

计算机、通信以及消费类电子产业的快速发展成为示波器发展的不竭动力&#xff1b;厂商不断从技术上对示波器进行改进更使其发展日新月异。 <?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />数字示波器自它诞生的第一天起&#xf…

网站上传后没有后台上海高端seo公司

一、明白社群运营的目的1、社群的目的确立任何一个社群(组织)成立的时分&#xff0c;都是承载着一定的目的的&#xff0c;这个目的就像是北极星一样&#xff0c;指引着我们的方向。确立运营目的的过程&#xff0c;也是在寻觅北极星的过程。社群运营属于触达用户的一种方式&…

网站备案幕布大小彩票网站的表格是如何做的

正题 题目大意 nnn个点的一棵树&#xff0c;每个节点有一个值valvalval和一个字符串SSS。对于每个点求∑x∈decp∑y∈decp(x<y)(valxxorvaly)∗∣LCP(Sx,Sy)∣\sum_{x\in dec_p}\sum_{y\in dec_p(x<y)}(val_x\ xor\ val_y)*|LCP(S_x,S_y)|x∈decp​∑​y∈decp​(x<y)…

综合网站开发设计中国建设银行网站用户是什么

在 XP 系统下不能建立叫 con 的文件! 不知其他朋友也是这样? 转载于:https://www.cnblogs.com/del/archive/2009/04/26/1444175.html

南通通州区网站制作wordpress 博客插件

1、手机触屏不灵敏小伙伴们经常说&#xff0c;我的手机偶尔会反应不灵敏。需要连续点击几次&#xff0c;有时候半天才有反应。这是为什么呢&#xff1f;这很可能是由于一些操作不当造成的&#xff1a;1.非原装充电器输出电压不稳定&#xff1b;2.屏幕保护膜导致触屏的不灵敏&am…

网站建设公司商务网站项目书网站建设专题页

承载16个量子点交叉条阵列的量子芯片&#xff0c;可无缝集成到棋盘图案&#xff08;图片来源&#xff1a;网络&#xff09; 由荷兰代尔夫特理工大学(TU Delft)和荷兰应用科学研究组织(TNO)组建的荷兰量子计算研究中心QuTech的研究人员开发了一种用相对较少的控制线来控制大量量…

童装网站建设目标宁波网站推广方案

文章目录 前言一、抽象类和接口对比二、举例说明三种情况1.接口实现类接口 2.抽象类实现类抽象类实现类(子类) 3.抽象类实现接口接口抽象类三个实现类 总结 前言 抽象类和接口其实都是抽象的一种,那么他俩有何异同呢? 抽象类实现接口的意义何在? 一、抽象类和接口对比 接口…

马鞍山建设网站马和人做人和牛做网站

告警解释 系统每天二十三点检查一次当前系统中的证书文件&#xff0c;如果当前时间距离过期时间不足告警阈值天数&#xff0c;则证书文件即将过期&#xff0c;产生该告警。告警阈值天数的配置请参考《管理员指南》的“配置证书即将过期告警阈值”章节。 当重新导入一个正常证…

广州开发小程序企业seo网络营销

Java内存模型: 内存分布情况及其关系: 主内存:Java内存模型规定所有的变量都保存在主内存中 工作内存:每个线程都有自己的工作内存,保存了该线程使用到的变量的主内存副本拷贝 主内存与工作内存的关系: 线程对变量的所有操作都必须在自己的工作内存中进行,不能直接读写主内存…

免费行情软件app网站大全下载u288北京住建局

智能优化算法应用&#xff1a;基于北方苍鹰算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于北方苍鹰算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.北方苍鹰算法4.实验参数设定5.算法结果6.参考…