• [面试直通版]操作系统之编程语言与运行原理(下)


    点击->操作系统复习的文章集<-点击

    目录​​​​​​​

    程序运行原理

    典型问题:

    CPU体系结构

    程序运行过程

    JIT技术

    链接方式

    典型问题:

    动态链接/静态链接


    • 程序运行原理

    • 典型问题:

    • 程序从源码到二进制文件经过哪些步骤?请简述
    • 请简述什么是JIT技术?
    • CPU体系结构

    • 二进制程序本质是一条一条的CPU指令
    • 之前说过,不同CPU体系结构的指令集不同,c/c++程序跨平台需要重新编译
    • 运行时从main函数开始执行
    • 程序如何加载进内存?如何定位到main函数地址?
    • 如何进行程序运行的内存初始化工作?
    • 各平台可执行文件:
    • MacOS:Mach-O
    • Linux:ELF
    • Windows:PE
    • 程序运行过程

    • 预编译->编译->汇编->链接->装载->运行
    • 方便描述以c/c++程序为例
    • 预编译
    • 预编译主要是做一些代码文本的替换工作
    • 如#define、#include、条件编译
    • 去掉代码注释
    • 编译
    • 之前讲过了
    • 汇编
    • 将汇编代码转为机器码
    • 链接
    • 目标文件仅仅是当前的源码文件编译成的二进制文件
    • 并没有经过链接过程,是不能够执行的
    • 来个例子:
    • 通过test.cpp得到了test.o
    • 但是test.cpp可能依赖了a.cpp以及b.cpp的源码文件
    • 而这2源码文件也需要单独去编译
    • 最后得到3个目标文件,然后再把这3个目标文件通过链接形成最终的可执行文件
    • 还有调用系统库、第三方库实现相关功能(如:输出到屏幕、系统sleep、new thread)
    • 因为依赖相关库实现相关功能,所以要再次编译再链接
    • 把当前的动/静态链接库链接到当前所编译的目标文件,形成可执行文件
    • 装载
    • 可执行文件在运行时需要加载进内存,是一个装载的过程
    • 需要确定的进程入口地址(main提供)
    • 完整的进程空间(操作系统提供)
    • JIT技术

    • Java由于它的特殊性,是编译+解释
    • JVM是与地址无关的字节码
    • 解释执行效率不如本地二进制执行效率
    • 来个优化
    • JIT技术(Just In Time):
    • 通常对于存在中间代码的运行系统(Java、Python等),解释执行过程的效率不如传统本地代码的执行效率
    • 在实现JIT的系统中,JIT可以在运行过程动态将中间字节码编译成本地代码,从而加快运行速度
    • 这里面要考虑性能优化收益是否大于编译消耗
    • 链接方式

    • 典型问题:

    • 请简述动态链接与静态链接的主要区别
    • 回顾链接
    • 不同目标文件之间组装为目标文件
    • 目标文件链接为可执行文件
    • 动态链接/静态链接

    • 库:
    • 库是写好的现有的,成熟的,可以复用的代码
    • 现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常
    • 链接库:
    • 制作成通用格式共享库,具备标准通用的加载接口,可以提供相同平台下不同程序使用的库
    • 动态/静态链接库:
    • 动态/静态特指链接库提供调用的不同形式,动态链接、静态链接各有优劣
    • 不同平台下动态/静态链接库区别:
    • Linux上动态链接库文件以.so结尾
    • 静态链接库文件以.a结尾
    • Windows上动态链接库文件以.dll结尾
    • 静态链接库文件主要以.lib结尾
    • 目标文件
    • 典型的4个段:
    • .text(代码段):程序执行代码
    • .data(数据段):已初始化全局变量
    • .bss(bss段):未初始化全局变量
    • 堆、栈...
    • 静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时
    • 静态链接
    • 由很多目标文件进行链接形成的是静态库,反之静态库也可以简单地看成是一组目标文件的集合,即很多目标文件经过压缩打包后形成的一个文件
    • 链接器在链接静态链接库的时候是以目标文件为单位的
    • 比如引用了静态库中的printf()函数,那么链接器就会把库中包含printf()函数的那个目标文件链接进来,如果很多函数都放在一个目标文件中,很可能很多没用的函数都被一起链接进了输出结果中
    • 由于运行库有成百上千个函数,数量非常庞大,每个函数独立地放在一个目标文件中可以尽量减少空间的浪费,那些没有被用到的目标文件就不要链接到最终的输出文件中
    • 静态链接的缺点很明显,一是浪费空间,因为每个可执行程序中对所有需要的目标文件都要有一份副本,所以如果多个程序对同一个目标文件都有依赖,如多个程序中都调用了printf()函数,则这多个程序中都含有printf.o,所以同一个目标文件都在内存存在多个副本;
    • 另一方面就是更新比较困难,因为每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序
    • 静态链接的优点就是,在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度快
    • 动态链接
    • 动态链接出现的原因就是为了解决静态链接中提到的两个问题,一方面是空间浪费,另外一方面是更新困难
    • 动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件
    • 动态链接的优点显而易见,就是即使需要每个程序都依赖同一个库,但是该库不会像静态链接那样在内存中存在多分,副本,而是这多个程序在执行时共享同一份副本;
    • 另一个优点是,更新也比较方便,更新时只需要替换原来的目标文件,而无需将所有的程序再重新链接一遍
    • 当程序下一次运行时,新版本的目标文件会被自动加载到内存并且链接起来,程序就完成了升级的目标
    • 但是动态链接也是有缺点的,因为把链接推迟到了程序运行时,所以每次执行程序都需要进行链接,所以性能会有一定损失
    • 动态链接与装载
    • 静态链接目标:
    • 只需要装载执行文件即可
    • 动态链接目标:
    • 还需要另外加载动态链接库
  • 相关阅读:
    CorelDRAW最新24.1.0.360版本更新介绍讲解
    windows如何把已安装的nodejs高版本降级为低版本&node多环境
    Kubernetes 上运行有状态应用的最佳实践 k8s
    微信小程序(原生)
    康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(三)
    Maven学习记录
    go泛型使用方法
    jenkins配置及实现接口自动化集成
    TCP和UPD的区别
    02 【JS表达式与操作符】
  • 原文地址:https://blog.csdn.net/weixin_59624686/article/details/126856317