编译示例

编译器(compiler)是将编程语言的代码转换为其他形式的软件,这种转换操作称为编译(compile)。

实际编译器有C语言的GCC(GNU Compiler Collection)、Java语言的编译器javac等。

编译示例

# 创建C语言程序
$ vim hello.c

#include <stdio.h>

int
main(int args, char **argv)
{
  printf("hello, world!\n");
  return 0;
}

# 生成名为hello的可执行文件(executable file)
$ gcc hello.c -o hello

# 运行生成的hello命令
$ ./hello
hello world!

疑问:

  • 可执行文件是这样的文件呢?
  • gcc命令是如何生成可执行文件的呢?
  • 可执行文件hello是经过哪些步骤运行起来的呢?

可执行文件

首先从GCC生成的可执行文件说起

现代的Linux上的可执行文件,通常指符合 ELF(Executable and Linking Format) 这种特定形式的文件。例如lscp这些命令(command)对应的实体文件都是可执行文件。

# Windows上查看可执行文件
$ file hello
hello: PE32 executable (console) Intel 80386, for MS Windows

# Linux上查看可执行文件
$ file hello

ELF文件包含了程序代码以及如何运行该程序的相关信息(元数据)。程序代码就是机器语言(machine language)的列表。机器语言是唯一一种CPU能够直接执行的语言,不同种类的CPU使用不同的机器语言。

GCC将C语言的程序转化为用机器语言描述的程序,将机器语言的程序按照ELF这种特定的文件格式注入文件,得到的就是可执行文件。

编译

gcc命令式如何将hello.c转换为可执行文件的呢?

hello.c 这样的单个文件来生成可执行文件时,虽然只需要执行一次 gcc 命令,但实际上其内部经历了如下 4 个阶段的处理。

  1. 预处理
  2. 狭义的编译
  3. 汇编
  4. 链接

上述处理统称为编译,严谨地说“狭义的编译”才是真正意义上的编译,这4个阶段的处理统称为 build

预处理

C语言的代码首先由预处理器(preprocessor)#include#define进行处理。

#include <stdio.h>

具体说来就是读入头文件,将所有的宏展开,这就是预处理(preprocess)preprocess是前处理的意思,其实就是在编译前进行处理。

狭义的编译

接着,编译器(compiler)对预处理器的输出进行编译,生成汇编语言(assemble language)的代码。一般来说,汇编语言的代码的文件扩展名为.s

汇编语言是由机器语言转换过来的人类较易阅读的文本形式的语言,机器语言是以CPU执行效率为第一要素设计的,用二进制代码表示,每个bit都有自己的含义,人类很难理解。因此,一般要使用与机器语言直接对应的汇编语言,以方便人类理解。

汇编

然后,汇编语言的代码由汇编器(assembler)转换为机器语言,这个处理过程称为汇编(assemble)

汇编器的输出称为目标文件(object file),一般来说,目标文件的扩展名为 .o

Linux中,目标文件也是ELF文件,既然都是ELF文件,那么究竟是目标文件还是可执行文件呢?这不是区分不了吗?这个不用担心。ELF文件中有用于提示文件种类的标志。

链接

目标文件本身还不能直接使用,无论是直接运行还是作为程序库(library)文件调用都不可以。将目标文件转换为最终可以使用的形式的处理称为链接(link)。使用程序库的情况下,会在这个阶段处理程序库的加载。

总结

build过程总结:C语言的代码经过预处理、编译、汇编、链接这4个阶段的处理,最终生成可执行文件。

生成可执行文件的过程

程序运行环境

程序运行的全过程

现代编程语言的运行过程中,运行环境所起的作用越来越大。

首先,链接的话题并非仅仅出现在build的过程中。如果使用共享库,那么在开始运行程序时,链接才会发生。最近广泛使用的动态加载(dynamic load),就是一种将所有链接处理放到程序运行时进行的手法。

其次,像Java和C#这种语言的运行环境中都有垃圾回收(GC, Garbage Collection)这一强大的功能,该功能对程序的运行有着很大的影响。

再次,在Java VM等具有代表性的Java的运行环境中,为了提高运行速度,采用了JIT编译器(Just In Time Compiler)。JIT编译器时在程序运行时进行处理,将程序转换为机器语言的编译器。也就是说,Java语言是在运行时进行编译的。

编程语言的运行方式

编译器会对程序进行编译,将其转换为可执行的形式。另外也有不进行编译,直接运行编译语言的方法。解释器(interpreter)就是这样的一个例子。解释器不将程序转换为别的语言,而是直接运行。例如Ruby和Perl的语言处理器就是用解释器来实现的。

运行语言的手段不止一种,例如C语言也可以用解释器来解释执行,Ruby也可以编译成机器语言或Java的二进制码。也就是说,编程语言与其运行方式可以自由搭配。因此,编译器也好,解释器也罢,都是处理并运行编程语言的手段之一,统称为编程语言处理器(programming language processor)

但是,根据语言的特点,其运行方式有适合、不适合该语言之说。一般来说,有静态类型检查(static type checking)、要求较高可靠性的情况下使用编译的方式;相反,没有静态类型检查、对灵活性的要求高于严密性的情况,则使用解释的方式。

静态类型检查是指在程序开始运行之前,对函数的返回值以及参数的类型进行检查的功能。与之相反,在程序运行过程中随时进行类型检查的方式称为动态类型检查(dynamic type checking)

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

推荐阅读更多精彩内容