运行helloworld程序,计算机做了什么?

#include <stdio.h>
int main(){
    printf("helloworld!");
}

当写下这个程序,点击运行⏯

这个过程计算机做了什么

一、编译系统

1.1 编译过程

在Unix系统上,由编译器把源文件转化为目标文件

gcc -c -o hello.c hello.o
gcc -o hello.o hello

-o:output

它的具体过程如下:


  • 预处理阶段:处理以 # 开头的预处理命令
  • 编译阶段:翻译成汇编文件;
  • 汇编阶段:将汇编文件翻译成可重定位目标文件
  • 链接阶段:将可重定位目标文件和 printf.o 等单独预编译好的目标文件进行合并,得到最终的可执行目标文件。

1.2 目标文件

  • 可执行目标文件:可以直接在内存中执行;
  • 可重定位目标文件:可与其它可重定位目标文件在链接阶段合并,创建一个可执行目标文件,如静态链接;
  • 共享目标文件:这是一种特殊的可重定位目标文件,可以在运行时被动态加载进内存并链接,如动态链接;

1.3 链接

编译的过程面向的是计算机,链接的过程面向的是人。如果没有链接,人们就不得不每次把需要用到的代码编译一遍,还需要自己在代码中填写相关的物理地址。

链接分为静态链接动态链接

1.3.1 静态链接

静态链接器以一组可重定位目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务:

  • 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。
  • 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。

1.3.2 动态链接

静态库有以下两个问题:

  • 当静态库更新时那么整个程序都要重新进行链接
  • 对于 printf 这种标准函数库,如果每个程序都要有printf的代码,这会极大浪费资源

共享库是为了解决静态库的这两个问题而设计的,在 Linux 系统中通常用 .so 后缀来表示,Windows 系统上它们被称为 DLL。它具有以下特点:

  • 在给定的文件系统中一个库只有一个文件,所有引用该库的可执行目标文件都共享这个文件,它不会被复制到引用它的可执行文件中;
  • 在内存中,一个共享库的 .text 节(已编译程序的机器代码)的一个副本可以被不同的正在运行的进程共享

二、操作系统

2.1 进程的创建

编译系统执行之后,会形成一个hello的可执行文件,windows下后缀是.exe

扫描二维码关注公众号,回复: 11248883 查看本文章
  1. 用户告诉操作系统执行hello程序

  2. 操作系统到外存找到该程序

  3. 操作系统分配内存,将程序装入内存

  4. 为执行hello程序创建执行环境(创建新进程 )

创建进程的准备工作:操作系统设置CPU上下文环境并跳到程序开始处

这个过程需要的主要寄存器是:

寄存器 含义 作用
PC 程序计数器 存放将要执行的指令地址
IR 指令寄存器 存放正在执行的指令
AC 累加器 临时存储体和累加操作

这里有两个主要问题:

  • 指令:程序的执行并不是一条条语句,而是一条条指令,每条指令执行完CPU会检查是否发生中断

  • CPU上下文:即程序计数器和累加器的值,在发生中断的时候,就要求硬件存储这两个值

2.2 进程的执行

  1. 程序的第一条指令执行
  2. 程序执行与printf对应的库函数、系统调用

产生系统调用,就会陷入内核态,执行内核的read函数

这个时候会提出I/O请求,同时这个hello程序就阻塞了

2.3 进程的阻塞

为什么会阻塞?

因为申请I/O的过程中需要进程等待,驱动程序需要写调用设备的状态寄存器,之后由设备控制器需要进行输出的准备。大概过程是:

  1. 操作系统分配设备
  2. 执行显示驱动程序
  3. 将像素写入存储映像区(显存)

在设备控制器进行准备的过程中,CPU调度新的进程来投入运行,这样能提高CPU的利用率,CPU与I/O系统并行工作

2.4 进程的唤醒

I/O完毕之后,CPU接收中断,处理中断,从而唤醒发出I/O请求的进程,这个时候hello进程就转为就绪态。

这个要注意,是就绪态,而不是直接就运行态,CPU处理完中断之后不一定执行hello进程


三、计算机硬件

硬件的部分显得不是特别重要,输出helloworld的硬件处理如下:

  1. 视频硬件将像素表示转换成一组模拟信号控制显示器(重画屏幕)
  2. 显示器发射电子束
  3. 显示屏上出现 hello world

在程序的执行过程中还有磁盘读取的一些操作,如转入内存

3.1 磁盘读文件的过程

数据在扇区

  • 逻辑编号,磁盘的逻辑地址转化为物理地址

    每个磁道分为很多扇区,用户文件的数据就存放在扇区上。获得扇区的编号:逻辑编号(也叫做磁盘的逻辑地址)操作系统需要把逻辑编号转换为物理地址。

    物理地址的构成:柱面号:半径相同的构成一个柱面;磁头号;扇区号

  • 送寄存器的相关值

    函数需要得到柱面号、磁头号和起始扇区号。然后将三者放到固定的寄存器中去。一旦启动中断,就开始了硬件上文件的读操作。

    操作系统实质上在做什么?写寄存器、调用中断

3.2 设备控制器

I/O系统除了用于I/O和存储信息的设备,还需要设备控制器。

参考

[1]:https://github.com/CyC2018/CS-Notes

猜你喜欢

转载自www.cnblogs.com/smallocean/p/12938464.html