再读《程序员的自我修养》

大学学习C语言时,书上面有一句话,程序就是数据和算法。面对着整型、字符串、浮点数等数据,还有冒泡、选择、堆等算法,好像程序确实如此。后来入门程序开发工作,变成了面对各种开发库的使用,UI的实现,业务的沟通和理解,好像一个程序不仅仅是数据和算法那么简单。

《程序员的自我修养》这本书,引导我从程序的最终运行方式(计算机的CPU不断读取物理内存中的指令和数据)角度,重新认识和理解开发的最终程序,再一次回归到程序就是数据和算法的论断。记得一句哲人说,认识有3个阶段。第一阶段是看山是山,看水是水;第二阶段是看山不是山,看水不是水;第三阶段,看山还是山,看水还是水。感谢这本书的作者,让我重新回到对程序的认识上。

1 CPU执行时只有指令和数据

无论什么样的程序,最终运行时,就是CPU在不断的工作。它工作的方式就是不断地从内存中读取指令和数据进行运算。这些指令和数据,都是以二进制的0和1进行存储。使用工具分析程序打包后的可执行文件时,能看到各种.text.data.rel.bss.got等不同的段分类,在调试程序时,能够看到程序运行的每一步,所对应的具体代码。这些都是开发工具对二进制指令和数据内容的相应翻译,将用于机器理解的二进制的内容,翻译为对应的高级(人类)语言。

从程序最终运行的角度去看,优化程序的方式可以有:减少执行的步骤,比如使用更优的算法、减少上下文的切换、合并指令等;加快读取的时间,比如使用缓存。当然还有一种釜底抽薪的解决方式,更换为更好的硬件产品,😄。

2 虚拟内存和物理内存

启动一个程序时,操作系统会开辟一个进程,建立虚拟内存到物理内存的映射,加载程序的运行库,最后跳转到程序的执行入口。CPU执行时,都是从物理内存中读取内容。通过计算机中的内存计算单元(MMU),可以将物理内存标记的地址,转换为程序进程的虚拟地址,进而装载相对应的可执行文件。这个过程就像将可执行文件的内容通过镜面(虚拟内存)映像到物理内存中一样,所以可执行文件也被称为映像文件。

虚拟内存是真实存在的吗?从名称就可以看出,它是不存在的。虚拟内存只是建立了一种读取可执行文件的方式,是用于物理内存读取可执行文件内容的中转站。就像在计算器中输入2X4,看到得到的结果是8。这是计算器通过内置的乘法公式计算出来的,我们能说乘法公式是在计算器中真实存在的吗?显然不能。虚拟内存就相当于计算器中的乘法公式,用来对可执行文件的内容进行转换。这种转换后的结果就像建立了一个专属于程序进程的内存,我们称它为虚拟内存。

3 目标文件和可执行文件

目标文件是编译器将源代码文件翻译成计算机可以理解的二进制文件,可执行文件是链接器将目标文件(单个或多个)和依赖库(一般都有)一起链接后,形成的计算机可以运行的二进制文件。以C语言为例,初始代码都在.c的文件中,通过编译,获得.o的目标文件。将目标文件和C运行库进行链接,获得最终的可执行文件.out。

本质上,目标文件和可执行文件都是文件,而且都是二进制文件。使用工具对两者进行分析,会看到都包含.bss.data.text.rodata等内容。这是两者相同的地方。相对于目标文件,为什么可执行文件就可以执行呢?寻找这个问题答案的过程,就是理解链接器作用的过程。简单来说,就是链接器将不同的目标文件的相同段进行合并,按照内存分页和地址对齐的原则对不同段重新分配虚拟空间,然后将指令涉及的符号按照虚拟空间的地址重新定位,最后指定程序的入口函数。这就形成了最终的可执行文件。

4 运行库

现在编程时,使用的基本都是高级语言。使用高级语言编写源代码,不仅仅在于它更容易使人理解,而且在于高级语言大都提供了便捷的运行库,让开发者可以不用太关心底层实现,专注于上层功能的实现。比如使用C语言开发时,使用scanf/printf函数就可以实现计算机的IO调用,使用malloc/free就可以实现内存的申请和释放,使用fopen/fwrite就可以实现文件的读写等等。这些都是因为C语言在标准库(stdlib)中进行了实现,开发时只要引用就可以了。这些高级语言编写的程序运行时,所有相关库的集合,就是运行库。

运行库分为两种存在静态和动态两种存在形式。使用静态运行库,在链接器生成可执行文件时,会将相关的静态运行库一起拷贝到执行文件中。使用动态运行库,会将可执行文件和相关运行库的链接过程,推迟到可执行文件启动时完成,这是一种牺牲部分时间,获得更大磁盘空间的选择。

总结

计算机的技术更新日新月异。像各种出现不久的开发语言go\ruby\flutter等,不同语言下出现的SDK更是数不胜数。甚至以为相对稳定的操作系统,就在近5年内,出现了鸿蒙和VisionOS。表面上,这些变化应接不暇,就像进入了一个卖各种美食的食宝街,转来转去,不知选择哪一家下口。面对众多的商家,心中若有想要都通吃一遍的想法,甚至会心生一丝心有余而力不足的恐惧。

作为程序开发者,抽丝剥茧,或者快刀斩乱麻,回到程序运行的最终形态去看,就是编译、链接和装载。回到上面的计算器的例子,表面上有珠算、速算、乘法口诀等等各种便捷计算方式,可底层终归是围绕加减乘除的数学规则。

计算机的大厦,就是由不同层次的积木累积而成。底层的硬件,像CPU\内存\主板\显示器\键盘等。对不同硬件的使用进行封装,就形成了操作系统。操作系统提供封装完善的API,方便不同语言的运行库使用。开发者使用运行库,顺利开发出新程序,在对应的操作系统运行。不同层次的内容不断更新,可是形成的这个整体框架,确是稳定不变的。

多彩纷繁的语言如同漫天繁星,与它们的距离遥远的仿佛深不可测。只专注于一个星球——地球的了解,却让我们获得了万有引力和相对论的真理。读这本《程序员的自我修养》的过程,就相当于去探索程序运行的本质。这也是我认为之所以命名为修养的原因。

喜欢和关注都是对我的鼓励和支持~
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容