标签(空格分隔): 程序人生
“Hello world!”是很多的程序员的第一个程序,不管是什么语言,“Hello world!”总被当作是程序员通向里另一个世界的大门,你真的知道一个“Hello world!”的程序是如何在计算机内部执行的吗?
1.编写一个“Hello world!”并执行
- 新建一个hello.c
root@vmuser-virtual-machine:/home/vmuser# vim hello.c
2.开始写一个“Hello World”
#include<stdio.h>
void main()
{
printf("Helllo World\n");
}
3.编译
root@vmuser-virtual-machine:/home/vmuser# gcc hello.c -o hello
//如果写的没有错误,那么将会在当前的目录下生成“hello”的可执行文件
4.执行
root@vmuser-virtual-machine:/home/vmuser# ./hello
如图所示
这样你的确是会写一个“Hello world!”了。然而并不是这样!
2.什么是程序?
“Hello world!”的生命周期是从一个源文件“hello.c”开始的,其实也就是一个文本文档,其实也就是一个由0和1组成的编码的集合。现代操作系统的大部门的文本文档采用的编码方式一般都为ASCII编码。看下图,我们看看一段“Hello world!”的程序的源码是如何在计算机内部表示的!
我们可以看到“hello world”在计算机内部的存贮方式,但是实际上只不过是一串的二进制的‘010101……’的编码序列这样给我们的启示是,程序其实就是计算机内部的一些信息,然而计算机语言的作用就是我们如何的编码和解码,从而实现一个特定的作用。
GCC的编译过程
编译 hello.c 命令很简单,但实际上,看似很简单的这一步操作,却隐藏了很多操作细 节。下面将通过这个示例,对其中的一些细节进行还原和了解。一个计算机程序,从编码到执行计算机内部要完成以下的几个过程:
- 预处理
预处理器(cpp)根据#开头的命令,修改原始的c程序,将#后面的内容代替为头文件本身的内容,并把它插入程序文本之中,结果就得到了另一个以hello.i为扩展名的c程序。
在这里GCC要加上参数 -E
root@vmuser-virtual-machine:/home/vmuser# gcc -E hello.c -o hello.i
此时会生成hello.i的程序
用vi编辑器打来之后
一个简单的Hello world 居然有800多行的代码
跳转到末尾
可以看出,其实多余的代码就是有#include
root@vmuser-virtual-machine:/home/vmuser/he# gcc -S hello.i
用vi打开hello.s文件,可以可以看到汇编代码
- 汇编
汇编器(as)的作用是将hello.s的汇编程序程序打包成可以重新定位的目标程序->hello.o,也可以叫做可执行文件
得到了汇编文件后,通过 gcc 就可以得到机器码了。在终端输入下列命令,可以得到 hello.o 文件。
root@vmuser-virtual-machine:/home/vmuser/he# gcc -c hello.s
那么此时万事大吉了吗?No!
- 链接
请注意,由于”hello word”程序用了printf函数,链接器(ld)的作用就是将printf.o的可rm执行文件已某种方式合并到hello文件中,这样才可以生成可执行的hello文件!
尽管已经得到了机器码,但还是不可以运行的,必须要经过链接才能运行。在终端输入 下列命令,将会得到可执行文件 a.out。
root@vmuser-virtual-machine:/home/vmuser/he# gcc hello.o
生成了a.out的可执行文件
a.out 是 gcc 默认输出文件名称,可以通过-o 参数指定新的文件名。例如加上“-o hello” 参数,将会生成 hello 文件,这个文件和 a.out 实际上是一样的,用 md5sum 命令计算文件校 验值,两者完全一样
链接可分为动态链接和静态链接:
动态链接使用动态链接库进行链接,生成的程序在执行的时候需要加载所需的动态 库才能运行。动态链接生成的程序小巧,但是必须依赖动态库,否则无法执行。
Linux 下的动态链接库实际是共享目标文件(shared object), 一般是.so 文 件,作用类似于 Windows
下的.dll 文件。 静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直 接运行,不过体积较大。Linux 下静态库是汇编产生的.o 文件的集合,一般以.a 文件形式出现。 gcc 默认是动态链接,加上-static
参数则采用静态链接。再来看 hello.c 示例,在链接的 时候加上-static 参数:
vmuser@Linux-host:hello$ gcc hello.o -static -o hello_static
可以看到,动态链接生成的文件大小是 8379字节, 而静态链接生成的文件却有 879558 字节,体积明显大了很多。
总的过程可以用图来描述
此时生成的文件才可以执行了!
(持续更新)