Loading

从Linux系统角度分析程序效率的影响因素

一.Linux系统概念模型

1.1 Linux概念模型

 

1 Linux概念模型

  上图所示是Linux系统的概念模型,可以看到,Linux操作系统是用户连接用户和硬件之间的桥梁。

  Linux操作系统最核心的内容即是“进程管理”功能。为了实现这一核心功能,这就引入了“三大法宝”(存储程序计算机,函数调用堆栈和中断)和“两把宝剑”(中断上下文,进程上下文)。

  用户程序的需求(如读写文件、驱动设备访问等),其处理流程就形如上图箭头方向所示,通常一个程序的顺利执行都需要经过系统调用、进程管理、文件管理以及各类硬件接口,等等,下面我们以设备驱动程序为例说明这一点。

1.2 举例:设备驱动程序(以open为例)

  在Linux操作系统中,我们可以用将驱动设备看成是字符设备或者块设备,这里假设我们访问的是一个字符设备,这样我们访问驱动程序本质上就是访问一个字符文件设备,可以通过文件系统提供的open(),write(),read()系统调用进行访问,我们以open为例,说明上述Linux概念原型是正确且逻辑自洽的。

  (1)用户程序调用open库函数。

  (2)库函数通过陷入指令,使得操作系统进入内核态,保存相关的寄存器后,跳转到中断向量表中处理异常的表项。

  (3)根据相关寄存器,获取系统调用号,调用对应的系统调用(本例中为sys_open)。

  (4)Sys_open根据参数,查找系统文件打开表,读取调用进程的root目录的iNode节点。

  (5)创建file数据结构,填写信息,并将iNode节点读入内存,根据iNode节点中的设备号获取到设备驱动程序。

  (6)用户程序在进程文件打开表中分配一个空闲数组保存file文件指针,并返回在进程文件打开表中的下标索引(即文件描述符)。

  可以看到,在以设备驱动访问过程的例子中,整体的操作过程,基本与上述的Linux系统概念原型一致,从而验证了我们的系统概念原型的正确性,逻辑自洽性。

二.应用程序在Linux上的性能分析

2.1 评价应用程序性能的指标

  对于一个应用程序的性能的优劣,评价通常可以按照以下几个指标来判定:

  (1)运行速度。通常一个应用程序的运行速度越快,该应用程序的性能较好。

  (2)内存利用率。内存使用率过高会使得CPU过大,过低则说明内存资源并没有被很好的利用起来。

  (3)平均响应时间。响应时长是指系统对请求作出响应的时间,用户对该指标有直观感受。

  (4)CPU利用率CPU使用率是你运行的程序占用的CPU资源,表示你的机器在某个时间点的运行程序的情况。使用率越高,说明你的机器在这个时间上运行了很多程序,反之较少。

  而我们在第一个专题中已经分析过了Linux操作系统的概念模型,我们不难看出,从大的框架来看,Linux的概念模型可以分解为两个部分,分别为硬件部分和软件部分,下面我们也将从这两个方面去讨论制约应用程序性能的因素。

2.2 硬件影响因素

2.3.1 CPU

  CPU的运算速度自然决定了用户程序的运行速度。同样的CPU处理器,主频和性能是线性关系,这很好理解,2倍的主频就是2倍的性能。

  和CPU密切相关的另一个影响性能的因素就是指令集。如RISC指令集和CISC指令集,他们的运用场景不同,在特定情景的性能下的表现自然也不尽相同。

2.3.2 内存

  正如上述内存利用率分析所示,内存使用率过高会使得CPU过大,过低则说明内存资源并没有被很好的利用起来。

2.3.3 I/O方式

  常见的I/O方式有以下几种:直接程序控制方式,中断驱动控制方式、DMA方式等。

  直接程序控制方式虽然非常简单,不需要太多的硬件支持,但是由于在这种工作模式下,CPU需要一直等待进行轮询,造成CPU利用率不高的问题。而当我们采用了中断控制方式的时候,当且仅当输入或者输出完成一个数据后,才需要CPU花费时间进行中断处理,这又一次应证了中断是Linux操作系统的“三大法宝”之一。

2.3 软件影响因素

2.3.1 进程调度算法

  一个好的进程调度算法通常需要考虑以下几点因素:CPU利用率、吞吐量、等待时间和相应时间等。

  进程调度的时候需要进入内核态,并切换虚拟地址空间,切换内核栈和硬件上下文,容易造成cache失效、页表切换等问题。进程的频繁切换容易造成资源浪费,开销很大。

  不同的进程其需求也不同,在Linux中,0~99号进程为实时进程,100~139号进程为普通进程。Linux的调度策略为时间片轮转或者是先来先服务。对于一个用户程序而言,需要为其设计合适的进程调度算法,这样才能有效的提高CPU利用率、响应时间等。

2.3.2 应用程序潜在的问题

  考虑以下两种程序:

//程序一
int main(void){
    int a[1000][1000]={0};
    for(int i = 0 ; i < 1000 ; i++){
        for(int j = 0 ; j < 1000 ; j++){
            a[i][j] = 1;
        }
    }
} 
//程序二 
//调换了内外循环变量的顺序,影响了cache命中率
int main(void){
    int a[1000][1000]={0};
    for(int j = 0 ; j < 1000 ; j++){
        for(int i = 0 ; i < 1000 ; i++){
            a[i][j] = 1;
        }
    }
} 

  程序一的功能和程序二的功能完全一致,但是程序一的性能会好于程序二。这是因为在c语言中数组是连续存储的,这就造成了程序二的缺页次数、cache命中率会远低于程序一。用户程序本身的写法也会影响该程序的性能。

2.3.3 应用程序的链接方式

  以c代码为例,我们需要进行预处理、编译、汇编和链接。对于链接,分为静态连接和动态连接。

  静态链接的执行速度快,编译的时候将所有的代码都链接进去,造成了最终生成的可执行文件通常较大。

  动态链接在编译时不直接复制可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统。但是可能会出现兼容性的问题。

三.总结

  本文总结了Linux操作系统的概念模型,并针对此概念模型的正确性、自洽性做了例子的分析。基于概念模型的Linux操作系统,分析了影响用户程序执行效率的若干因素。所学甚浅,有错误的地方还希望多多评论讨论,若是抛砖引玉,则不甚荣幸。

posted @ 2021-05-10 22:01  dlzjc  阅读(409)  评论(0)    收藏  举报