最新细说:程序运行的环境和运行过程,再看不懂请自行面壁,震撼发布

总结

三个工作日收到了offer,头条面试体验还是很棒的,这次的头条面试好像每面技术都问了我算法,然后就是中间件、MySQL、Redis、Kafka、网络等等。

  • 第一个是算法

关于算法,我觉得最好的是刷题,作死的刷的,多做多练习,加上自己的理解,还是比较容易拿下的。

而且,我貌似是将《算法刷题LeetCode中文版》、《算法的乐趣》大概都过了一遍,尤其是这本

《算法刷题LeetCode中文版》总共有15个章节:编程技巧、线性表、字符串、栈和队列、树、排序、查找、暴力枚举法、广度优先搜索、深度优先搜索、分治法、贪心法、动态规划、图、细节实现题

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

《算法的乐趣》共有23个章节:

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

  • 第二个是Redis、MySQL、kafka(给大家看下我都有哪些复习笔记)

基本上都是面试真题解析、笔记和学习大纲图,感觉复习也就需要这些吧(个人意见)

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

  • 第三个是网络(给大家看一本我之前得到的《JAVA核心知识整理》包括30个章节分类,这本283页的JAVA核心知识整理还是很不错的,一次性总结了30个分享的大知识点)

最新出炉,头条三面技术四面HR,看我如何一步一步攻克面试官?

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

细说:程序运行的环境和运行过程,再看不懂请自行面壁

对于不太常用的内存数据,操作系统会写到磁盘上,以便腾出更多可用的物理内存。

当然,也存在没有操作系统的情况,这个时候你的程序所使用的内存就是物理内存,我们必须自己做好内存的管理。

对于这个内存,该怎么用呢

本质上来说,你想怎么用就怎么用,并没有什么特别的限制。一个编译器的作者,可以决定在哪儿放代码,在哪儿放数据,当然了,别的作者也可能采用其他的策略。实际上,C 语言和 Java 虚拟机对内存的管理和使用策略就是不同的。

尽管如此,大多数语言还是会采用一些通用的内存管理模式。以 C 语言为例,会把内存划分为代码区、静态数据区、栈和堆。

细说:程序运行的环境和运行过程,再看不懂请自行面壁

一般来讲,代码区是在最低的地址区域,然后是静态数据区,然后是堆。而栈传统上是从高地址向低地址延伸,栈的最顶部有一块区域,用来保存环境变量。

代码区(也叫文本段)存放编译完成以后的机器码。这个内存区域是只读的,不会再修改,但也不绝对。现代语言的运行时已经越来越动态化,除了保存机器码,还可以存放中间代码,并且还可以在运行时把中间代码编译成机器码,写入代码区。

静态数据区保存程序中全局的变量和常量。它的地址在编译期就是确定的,在生成的代码里直接使用这个地址就可以访问它们,它们的生存期是从程序启动一直到程序结束。它又可以细分为 Data 和 BSS 两个段。Data 段中的变量是在编译期就初始化好的,直接从程序装在进内存。BSS 段中是那些没有声明初始化值的变量,都会被初始化成 0。

堆****适合管理生存期较长的一些数据,这些数据在退出作用域以后也不会消失。比如,我们在某个方法里创建了一个对象并返回,并希望代表这个对象的数据在退出函数后仍然可以访问。

而栈适合保存生存期比较短的数据,比如函数和方法里的本地变量。它们在进入某个作用域的时候申请内存,退出这个作用域的时候就可以释放掉。

讲完了 CPU 和内存之后,我们再来看看跟程序打交道的操作系统。

2. 程序和操作系统的关系

==============

程序跟操作系统的关系比较微妙:

一方面我们的程序可以编译成不需要操作系统也能运行,就像一些物联网应用那样,完全跑在裸设备上。另一方面,有了操作系统的帮助,可以为程序提供便利,比如可以使用超过物理内存的存储空间,操作系统负责进行虚拟内存的管理。

在存在操作系统的情况下,因为很多进程共享计算机资源,所以就要遵循一些约定。这就仿佛办公室是所有同事共享的,那么大家就都要遵守一些约定,如果一个人大声喧哗,就会影响到其他人。

程序需要遵守的约定包括:程序文件的二进制格式约定,这样操作系统才能程序正确地加载进来,并为同一个程序的多个进程共享代码区。在使用寄存器和栈的时候也要遵守一些约定,便于操作系统在不同的进程之间切换的时候、在做系统调用的时候,做好上下文的保护。

所以,我们编译程序的时候,要知道需要遵守哪些约定。因为就算是使用同样的 CPU,针对不同的操作系统,编译的结果也是非常不同的。

好了,我们了解了程序运行时的硬件和操作系统环境。接下来,我们看看程序运行时,是怎么跟它们互动的。

程序运行的过程

=======

你天天运行程序,可对于程序运行的细节,真的清楚吗?

1. 程序运行的细节

===========

首先,可运行的程序一般是由操作系统加载到内存的,并且定位到代码区里程序的入口开始执行。比如,C 语言的 main 函数的第一行代码。

每次加载一条代码,程序都会顺序执行,碰到跳转语句,才会跳到另一个地址执行。CPU里有一个指令寄存器,里面保存了下一条指令的地址。

细说:程序运行的环境和运行过程,再看不懂请自行面壁

假设我们运行这样一段代码编译后形成的程序:

int main(){

int a = 1;

foo(3);

bar();

}

int foo(int c){

int b = 2;

return b+c;

}

int bar(){

return foo(4) + 1;

}

我们首先激活(Activate)main() 函数,main() 函数又激活 foo() 函数,然后又激活 bar()函数,bar() 函数还会激活 foo() 函数,其中 foo() 函数被两次以不同的路径激活。

细说:程序运行的环境和运行过程,再看不懂请自行面壁

我们把每次调用一个函数的过程,叫做一次活动(Activation)。每个活动都对应一个活动记录(Activation Record),这个活动记录里有这个函数运行所需要的信息,比如参数、返回值、本地变量等。

目前我们用栈来管理内存,所以可以把活动记录等价于栈桢。栈桢是活动记录的实现方式,我们可以自由设计活动记录或栈桢的结构,下图是一个常见的设计:

细说:程序运行的环境和运行过程,再看不懂请自行面壁

  • 返回值:一般放在最顶上,这样它的地址是固定的。foo() 函数返回以后,它的调用者可以到这里来取到返回值。在实际情况中,我们会优先通过寄存器来传递返回值,比通过内存传递性能更高。

  • 参数:在调用 foo 函数时,把参数写到这个地址里。同样,我们也可以通过寄存器来传递,而不是内存。

  • 控制链接:就是上一级栈桢的地址。如果用到了上一级作用域中的变量,就可以顺着这个链接找到上一级栈桢,并找到变量的值。

  • 返回地址:foo 函数执行完毕以后,继续执行哪条指令。同样,我们可以用寄存器来保存这个信息。

  • 本地变量:foo 函数的本地变量 b 的存储空间。

  • 寄存器信息:我们还经常在栈桢里保存寄存器的数据。如果在 foo 函数里要使用某个寄存器,可能需要先把它的值保存下来,防止破坏了别的代码保存在这里的数据。这种约定叫做被调用者责任,也就是使用寄存器的人要保护好寄存器里原有的信息。某个函数如果使用了某个寄存器,但它又要调用别的函数,为了防止别的函数把自己放在寄存器中的数据覆盖掉,要自己保存在栈桢中。这种约定叫做调用者责任

细说:程序运行的环境和运行过程,再看不懂请自行面壁

你可以看到,每个栈桢的长度是不一样的。

用到的参数和本地变量多,栈桢就要长一点。但是,栈桢的长度和结构是在编译期就能完全确定的。这样就便于我们计算地址的偏移量,获取栈桢里某个数据。

总的来说,栈桢的设计很自由。但是,你要考虑不同语言编译形成的模块要能够链接在一起,所以还是要遵守一些公共的约定的,否则,你写的函数,别人就没办法调用了。

在之前的文章中我提到过栈桢,这次我们用了更加贴近具体实现的描述:栈桢就是一块确定的内存,变量就是这块内存里的地址。在下一讲,我会带你动手实现我们的栈桢。

2.从全局角度看整个运行过程

==============

了解了栈桢的实现之后,我们再来看一个更大的场景,从全局的角度看看整个运行过程中都发生了什么。

细说:程序运行的环境和运行过程,再看不懂请自行面壁

代码区里存储了一些代码,main 函数、bar 函数和 foo 函数各自有一段连续的区域来存储代码,我用了一些汇编指令来表示这些代码(实际运行时这里其实是机器码)。

假设我们执行到 foo 函数中的一段指令,来计算“b+c”的值,并返回。这里用到了mov、add、jmp 这三个指令。mov 是把某个值从一个地方拷贝到另一个地方,add 是往

总结

至此,文章终于到了尾声。总结一下,我们谈论了简历制作过程中需要注意的以下三个部分,并分别给出了一些建议:

  1. 技术能力:先写岗位所需能力,再写加分能力,不要写无关能力;
  2. 项目经历:只写明星项目,描述遵循 STAR 法则;
  3. 简历印象:简历遵循三大原则:清晰,简短,必要,要有的放矢,不要海投;

以及最后为大家准备的福利时间:简历模板+Java面试题+热门技术系列教程视频

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

679864713)]

[外链图片转存中…(img-1q15qQvh-1715679864713)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值