详解程序执行过程

目录

前言

翻译环境

编译=预编译+编译+汇编

一、预编译

二、编译

三、汇编

链接

 执行环境


前言

每次用编译器写完一个程序后,我们会进行调试和执行,将代码的结果输出在我们的电脑屏幕上,但是我们并不清楚,为什么我们写的这些代码,可以转为我们想要的结果呢?

其实,在ANSI C(标准C) 的任何一种实现中,都存在两个不同的环境,即翻译环境执行环境。翻译环境内,代码被转换为可执行的机器指令。执行环境内,它用于实际执行的代码。

那么,我们的程序就是进行了这两个过程,才最终将我们想要的结果输出在屏幕上。

翻译环境

翻译环境下,程序会经过两个阶段,一个是编译,一个是链接。在一个工程里面,我们可能会有多个不同的源文件(.c后缀),那么这些源文件会通过编译器进行单独处理,会生成对应的目标文件(.obj后缀),而再经过链接之后,链接器会把这些目标文件和链接库连接起来。生成可执行程序(.exe后缀)。

通过上图我们可以看到,每个源文件都是经过编译器会生成一个对应的目标文件,转换成为对应的目标代码。然后再由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且也会搜索程序员个人的程序库,将需要的函数链接到程序中。

编译=预编译+编译+汇编

编译过程在细分下来可以分为三个环节,预编译、编译和汇编

一、预编译

在预编译这个阶段,编译器会进行的三个主要操作:

  1. 头文件的包含。在预编译阶段,编译器会将代码所包含的头文件替换成头文件的内容。通常,我们的代码会加上#include <stdio.h>这个头文件,这是在预编译的时候,就会去引用这个头文件的所有内容。
  2. #define 定义的符号替换。我们通常使用define定义标识符和宏。假设,我们这里顶一个一个MAX为100,#define MAX 100 ,那么在预编译阶段,我们程序中的MAX会被直接替换成100。
  3. 注释的删除。要知道一段程序中的注释通常是程序员在写代码过程中对代码的解释,这些解释对于程序来说是没有影响的。所以会在预编译这个阶段,将代码的注释进行删除

二、编译

编译阶段,最终是为了将C代码翻译成汇编代码,过程比较复杂,主要包括四个步骤:

  1. 词法分析。这一过程是将字符序列转为单词序列。这里的单词是一个字符串,是构成源代码的最小单位。从输入字符流中生成单词的过程叫作单词化,同时会对单词进行分类。比如:sum = 2+3; 将会拆成sum、=、2、+、3 这些单词。
  2. 语法分析。这一过程是分析单词符号串是否形成符合语法规则的语法单位。如表达式、赋值、循环等,最终是否构成一个符合要求的程序,再按照对应语言的语法规则检查每条语句是否正确。
  3. 语义分析。语义分析是对结构上正确的源程序进行上下文有关性质的审查,进行类型审查。比如语义分析的一个工作是进行类型审查,审查每个运算符是否具有语言规范允许的运算对象,当不符合语言规范时,编译程序 应报告错误。
  4. 符号汇总。这个环节会将源文件的全局函数的函数名进行汇总。

三、汇编

这一步是将汇编指令转换成二进制指令存放在一个obj后缀的目标文件中,同时会给每个源文件汇总出来的符号分配一个地址,然后生成一个符号表。

链接

在链接阶段,编译器主要完成两个任务:

  1. 合并段表。在汇编结束生成的obj文件,内部其实会被划分为几个段,在链接过程中会将这些段进行合并。
  2. 符合表的合并和重定位。在链接过程中,我们会对不同的符合分配一个相应的地址。而有的时候,一些符号在它所处的文件中并不存在,存在于另一个文件中,这时候我们会提前分配一个无意义的地址。在合并之后,会将合法的地址重新定位覆盖原来无意义的地址。

 执行环境

程序执行的过程:

  1. 程序载入内存。一般这是由操作系统进行。在独立的环境中,程序的载入手动安排,也可以通过可执行代码置入只读内存来完成。
  2. 程序的执行是由main函数开始。
  3. 开始执行程序代码,使用一个运行时堆栈,存储函数的局部变量和返回地址,同时在静态区存储静态变量,直到程序结束。
  4. 终止程序。main函数结束或者意外结束。
  • 22
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Docker是一种虚拟化技术,通过容器化技术可以轻松地打包应用程序和依赖项,并在任何地方进行部署和运行。在Docker中运行Python程序的过程如下: 1. 编写Dockerfile 首先,需要编写Dockerfile来描述如何构建Docker镜像。在Dockerfile中,需要指定基础镜像、安装Python依赖项、拷贝Python代码等操作。 例如,以下是一个简单的Dockerfile示例: ``` FROM python:3.8 WORKDIR /app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "app.py"] ``` 其中: - `FROM python:3.8`:指定基础镜像为Python 3.8。 - `WORKDIR /app`:指定工作目录为`/app`。 - `COPY requirements.txt ./`:将当前目录下的`requirements.txt`文件拷贝到容器中的`/app`目录。 - `RUN pip install --no-cache-dir -r requirements.txt`:安装Python依赖项。 - `COPY . .`:将当前目录下的所有文件拷贝到容器中的`/app`目录。 - `CMD ["python", "app.py"]`:指定容器启动时执行的命令。 2. 构建Docker镜像 执行以下命令构建Docker镜像: ``` docker build -t my-python-app . ``` 其中,`my-python-app`是镜像名称,`.`表示Dockerfile所在目录。 3. 运行Docker容器 使用以下命令运行Docker容器: ``` docker run -it --rm my-python-app ``` 其中,`my-python-app`是镜像名称。 4. 查看运行日志 在控制台中可以看到Python程序的运行日志。 以上就是在Docker中运行Python程序的基本流程。需要特别注意的是,如果Python程序需要连接其他服务,需要在Dockerfile中添加相应的依赖项和环境变量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值