• 运行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

    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. 执行显示驱动程序

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

    2.4 进程的唤醒

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

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


    这个过程需要采用CPU的调度算法

    三、计算机硬件

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

    在程序的执行过程中还有磁盘读取的一些操作

    3.1 磁盘读文件的过程

    数据在扇区

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

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

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

    • 送寄存器的相关值

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

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

    3.2 设备控制器

    主机I/O系统的结构是:

    计算机 ------- I/O通道 -------- 控制器 ---------设备

    设备控制器的共性部分:

    I/O逻辑需要将命令和地址译码,驱动外设产生动作

    参考

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

    [2]:https://my.oschina.net/hosee/blog/673628?p=%7b%7bcurrentPage+1%7d%7d

  • 相关阅读:
    RHEL7.2安装及配置实验环境
    VMwareworkstation 12安装
    Iterator主要有三个方法:hasNext()、next()、remove()详解
    httpclient
    http接口测试——Jmeter接口测试实例讲解
    java获取Excel的导出
    java获取Excel的导入
    java的post请求
    java的get请求
    Python3 列表(List)基础
  • 原文地址:https://www.cnblogs.com/smallocean/p/12938464.html
Copyright © 2020-2023  润新知