关于编译代码你应该知道的
创始人
2024-03-02 13:11:52
0

用这个方便的捕鼠器比喻来理解编译代码。

源代码必须要经过编译才能够运行程序,而对于开源软件,每个人都可以获取源代码。无论你是自己编写了代码,想要编译和运行它,还是下载了某人的项目来尝试它,了解如何通过 编译器 处理源代码,以及编译器如何处理这些代码,这都很有用。

创建一个更好的捕鼠器

一般情况我们不会将一个捕鼠器比作电脑,但不管你信不信,它确实与你正在使用的设备(手机或电脑)的 CPU 有一些相似之处。经典的捕鼠器(我说的不是 ?)有两种状态:打开或者释放。你可以认为 打开 是将捕鼠器设置好准备捕获老鼠,以及 释放 是捕鼠器被老鼠触发。某种意义上来说,捕鼠器就像是一台有鼠标的电脑。你可以想象一下这个代码,用一种虚构的语言来描述这个过程:

if mousetrap == 0 then
  There's a mouse!
else
  There's no mouse yet.
end

换句话说,你可以基于捕鼠器的状态发现是否有老鼠(数据)。当然,捕鼠器不是万无一失的,有可能有一只老鼠在捕鼠器旁边,由于老鼠还没有触发捕鼠器,所以它的状态还是 打开 的。因此该程序可以进行改进,这都是非常典型的。

开关

总的来说,捕鼠器就是一个开关。你会在家里使用开关打开灯。可以从开关中获得许多信息。比如,人们会从你家灯的状态了解到你是否在家。

你可以根据邻居家灯的状态来改变行为。如果邻居家所有的灯都熄灭了,那么请关掉你大声的音乐,因为人们可能已经上床睡觉了。

CPU 也使用这样的逻辑,只不过乘以几个数量级,缩小到了微观级别。当 CPU 在特定寄存器上接收到电信号时,可以触发其他一些寄存器,然后触发另一个,以此类推。如果这些寄存器有特定的意义,那么就可以通信。也许激活同一主板上某处的芯片,或者使 LED 亮起,或者改变屏幕上的像素颜色。

种瓜得瓜,种豆得豆。如果你真的想在多个位置而不是仅限于一处发现老鼠,但是你只有一个捕鼠器,那你应该开发一个应用才行。使用网络摄像头和一些基本的图像识别软件,你可以建立空厨房的模型,然后扫描变化。当老鼠进入厨房,在原先没有老鼠的图像上会有像素的变化。记录下这些数据,如果有无人机可以追踪老鼠并捕获会更好,这样就可以将老鼠赶出厨房了。这时,你通过打开和关闭信号的魔法,创造了一个更好的捕鼠器。

编译器

代码编译器将人们可阅读的代码转换成 CPU 可以理解的机器语言。这是非常复杂的过程,因为 CPU 非常复杂(甚至比捕鼠器更加复杂),同时因为该过程比严格“需要”的更加灵活。并不是所有的编译器都很灵活。有一些编译器只有一个目标,它们只会处理特定格式的代码文件,处理过程也因此而简单明了。

幸运的是,现代的通用编译器并不简单。它们允许你编写不同语言的代码,也允许你用不同的方式链接库文件,并且可以生成运行在不同架构上的文件。GNU 编译器集合(GCC)的 gcc 编译器 --help 会输出超过 50 行的选项,LLVM 的 clang 编译器的 --help 输出超过 1000 行。GCC 指导手册的字数超过 10 万。

当你在编译代码时会有很多选项。

当然,大多数人并不需要知道所有的选项。我从未读过 GCC 的手册页,因为它们是针对 Objective-C、Fortran 以及我从未听说过的芯片架构的。不过我重视它将代码编译为不同的架构 —— 64 位或者 32 位 —— 的能力,以及在其他行业已经落后的计算机上运行开源软件的能力。

编译生命周期

同样重要的是,理解编译代码的不同阶段。这是一个简单的 C 语言程序的生命周期:

  1. 带有宏定义的 C 源代码 .c 文件,用 cpp 预处理为 .i 文件。
  2. 扩展了宏定义的 C 源代码 .i 文件,会被 gcc 转译成 .s 文件。
  3. 以汇编语言写的文本文件 .s 文件被汇编为目标 .o 文件。
  4. 带有 CPU 指令的二进制目标代码,以及其他目标文件和库 *.o 文件,以内存区域无关的偏移量,使用 ld 链接以生成可执行文件。
  5. 最终的二进制文件要么包含所有需要的目标,要么设置以动态链接库 *.so 文件加载。

你可以试试这个简单示例(可能需要对库路径做一些调整):

$ cat << EOF >> hello.c
 #include
 int main(void)
 { printf("hello world\n");
   return 0; }
   EOF
$ cpp hello.c > hello.i
$ gcc -S hello.i
$ as -o hello.o hello.s
$ ld -static -o hello \
  -L/usr/lib64/gcc/x86_64-slackware-linux/5.5.0/ \
  /usr/lib64/crt1.o /usr/lib64/crti.o hello.o \
  /usr/lib64/crtn.o  --start-group -lc -lgcc \
  -lgcc_eh --end-group
$ ./hello
hello world

可获得的知识

计算机已经变得非常强大,并且用户友好。请不要走向这两种可能的极端中的任何一种:计算机不像捕鼠器和电灯开关那么简单,但它们也不是无法理解的。你可以了解编译代码、如何链接以及针对不同架构进行编译。一旦你知道了,你就可以更好地调试代码。你可以理解你下载的代码,甚至可以修复其中的一两个错误。同时从理论上来讲,你可以建造一个更好的捕鼠器,或者用捕鼠器造一个 CPU。由你决定。


via: https://opensource.com/article/22/10/compiling-code

作者:Alan Smithee 选题:lkxed 译者:Donkey-Hao 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

相关内容

华为仓颉编程语言首个 LT...
IT之家 7 月 1 日消息,华为仓颉编程语言首个 LTS 版本 ...
2025-07-01 21:12:49
VS2022配置工程的编译...
VS2022配置工程的编译路径(输出目录和中间目录&...
2025-06-01 19:24:39
编译原理个人作业--第二章
第二章 6 文法G6G_6G6​为 N→D∣NDN\rightar...
2025-05-31 13:52:40
Ubuntu20.4配置a...
Ubuntu20.4配置arm交叉编译环境 我是在虚拟机中配置的&...
2025-05-31 12:39:52
关于导入、编译、烧录S32...
问题来自于实践。 在学习了EB关于相关模块的配置之后,...
2025-05-31 10:37:52
【UNIX 环境编程】GC...
💭 写在前面:本文将介绍如何使用 G...
2025-05-31 02:18:08

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
从 Yum 更新中排除特定/某... 作为系统更新的一部分,你也许需要在基于 Red Hat 系统中由于应用依赖排除一些软件包。如果是,如...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...
如何检查你的 Linux 系统... 不知道在使用哪个初始化系统?以下是方法。每个主流 Linux 发行版(包括 Ubuntu、Fedor...