码迷,mamicode.com
首页 > 其他好文 > 详细

实验总结分析报告:从系统的角度分析影响程序执行性能的因素

时间:2021-05-24 10:15:47      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:冯诺依曼   opera   word   linux操作   汇编   函数调用   cal   次数   void   

一个精简的Linux系统概念模型

  课程一开始,孟老师从冯诺依曼体系结构开始讲起,并深入了解了存储程序计算机的工作原理,逐步理解计算机存储系统的层次结构、总线结构、内存、I/O等。

1、基本汇编语言

  汇编语言有两种,AT&T汇编和Intel汇编,而linux采用的是AT&T汇编。汇编指令包含操作码和操作数,操作码主要?些常见的汇编指令,最常见的汇编指令是mov指令,movb中的b是指8位,movw中的w是指16位,movl中的l是指32位,movq中的q是指64位;操作数分为立即数、寄存器和存储器3种。理解汇编语言,必须了解其语法规则,有寄存器寻址,立即寻址,直接寻址,间接寻址等。

  在32位系统和64位系统中寄存器的命名是不同的,在32位系统中,寄存器为eax、ebx等e开头,而64位系统中,寄存器名称为rax、rbx等以r开头。

2、进程

  进程,是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,是系统进行资源分配的基本单位。

  • 进程创建

  创建一个进程是复制当前进程的信息,就是通过_do_fork函数来创建了一个新进程。因为父进程和子进程的绝大部分信息是完全一样的,一些不一样的信息比如 pid 的值和内核堆栈。接着将新进程链接到各种链表中,其中thread数据结构记录子进程执行上下文的关键信息。

  • 进程状态

    进程的三种基本状态:运行、阻塞和就绪。

    • 运行状态:获得CPU的进程处于此状态,对应的程序在CPU上运行着。

    • 阻塞状态:为了等待某个外部事件的发生(如等待I/O操作的完成,等待另一个进程发来消息),暂时无法运行。也成为等待状态。

    • 就绪状态:具备了一切运行需要的条件,由于其他进程占用CPU而暂时无法运行。

  • 进程调度

  进程上下文切换时需要保存要切换进程的相关信息(如thread.sp与thread.ip),这与中断上下文的切换是不同的。中断是在?个进程当中从进程的用户态到进程的内核态,或从进程的内核态返回到进程的用户态,而切换进程需要在不同的进程间切换。但?般进程上下文切换是嵌套到中断上下文切换中的,比如系统调用作为?种中断先陷入内核,即发生中断保存现场和系统调用处理过程,其中调用了schedule函数发生进程上下文切换,当系统调用返回到用户态时会恢复现场,至此完成了保存现场和恢复现场,即完成了中断上下文切换。

3、用户态和内核态

  一般的操作系统对执行权限进行分级,分别为用保护态和内核态。用户态相较于内核态有较低的执行权限,很多操作是不被操作系统允许的。

  内核态相当于一个介于硬件与应用之间的层,内核有ring 0的权限,可以执行任何cpu指令,也可以引用任何内存地址,包括外围设备, 例如硬盘, 网卡,权限等级最高。

  用户态则权利有限,例如在内存分配中,有一部分内存是仅为内核态使用的,用户态code则不允许访问那些内存地址,每个进程只允许访问自己申请到的内存。而且不允许访问外围设备。另外在执行cpu指令的时候也可以被高优先级抢占。

4、中断

  如果我们的电脑只有一个 CPU 的话,任何程序都必须以串行的方式、轮流调度到 CPU 上运行,而为了使得程序能够在CPU上并发的执行,我们需要中断来进行处理;有了中断,我们才可以 “ 同时 ” 享受计算机的多种服务。

  中断分外部中断(硬件中断)和内部中断(软件中断),内部中断又称为异常(Exception),异常又分为故障(fault)和陷阱(trap)。

  从能否被屏蔽的角度,中断又可分为:

  • 可屏蔽中断——I/O设备发出的所有中断请求(IRQ)都可以产生可屏蔽中断。

  • 非屏蔽中断——只有几个特定的危急事件才引起非屏蔽中断。如硬件故障或是断电。

  异常分为:

  • 处理器探测异常

    • 由CPU执行指令时探测到一个反常条件时产生,如溢出、除0错等

  • 编程异常

    • 由编程者发出的特定请求产生,通常由int类指令触发

5、系统调用

  系统调用是一种特殊的中断,它利用陷阱(trap)这种软件中断方式主动从用户态进入内核态的;相反,硬件中断是被动的,在用户态进程执行时,硬件中断信号到来,用户态进程被挂起,进入内核态,然后执行这个中断对应的中断服务例程。

  系统调用执行过程:

  一般地,系统调用都是通过软件中断实现的,x86系统上的软件中断由int $0x80指令产生,而128号异常处理程序就是系统调用处理程序system_call(),它与硬件体系有关,在entry.S中用汇编写。当用户态进程调用?个系统调用时,CPU切换到内核态并开始执行system_call函数,其中根据系统调用号调用对应的内核处理函数。

  具体地,软中断指令int 0x80执行时,系统调用号会被放入eax寄存器,这样,system_call函数可以读取eax寄存器获得当前系统调用的系统调用号,将其乘以4生成偏移地址,然后以sys_call_table为基址,基址加上偏移地址所指向的内容即是应该执行的系统调用服务例程的地址。此时,可以真正执行sys_xyz()。

6、文件系统

  文件系统,就是操作系统中实现文件统一管理的一组软件、被管理的文件以及为实施文件管理所需要的一些数据结构的总称。

  文件系统的结构包括在磁盘上的结构和在内存中的结构。这些结构随操作系统和文件系统的不同而不同,但又有一些共同的规律。如,在磁盘上,文件系统有多少个磁盘块、空闲磁盘块数、目录结构、文件数据区等。

  linux下读文件,调用read()函数:

  (1)read是系统调用,执行软中断指令int 0x80;

  (2)系统调用号被存入eax寄存器,system_call函数调用真正的系统调用服务例程sys_read()函数;

  (3)函数调用读取后,返回。

7、影响应用程序性能表现的因素

  通过使用perf性能优化工具,对程序进行分析。

 分析结果主要参数:
  task‐clock是表示目标任务真正占用处理器的时间,单位是毫秒。也称任务执行时间
  context-switches是系统发生上下文切换的次数
  CPU-migrations是任务从一个处理器迁往另外一个处理器的次数
  page-faults是内核发生缺页的次数

(1)列优先遍历

 #include <iostream>
 #include <vector>
 using namespace std;
 void sum_col(vector<vector<int>> num) { //列优先
     int sum = 0;
     for(int i = 0 ; i < 1000; i++)
         for(int j = 0 ; j < 1000; j++)
             sum += num[j][i];
 }
 int main() {
     vector<vector<int>> num(1000, vector<int>(1000, 1));
     sum_col(num);
     return 0;
 }

  使用perf工具对代码进行分析。

技术图片

(2)行优先遍历

 #include <iostream>
 #include <vector>
 using namespace std;
 void sum_row(vector<vector<int>> num) { //行优先
     int sum = 0;
     for(int i = 0 ; i < 1000; i++)
         for(int j = 0 ; j < 1000; j++)
             sum += num[i][j];
 }
 ?
 int main() {
     vector<vector<int>> num(1000, vector<int>(1000, 1));
     sum_row(num);
     return 0;
 }

  使用perf工具进行分析。

技术图片

  分析:使用perf工具可以清晰的看出,行优先程序所需要task-clock变少了,且系统没有发生上下文的切换,运行时间更低。

8、致谢

  感谢这个学期孟老师与李老师的指导,让我对linux操作系统有了更深的理解。

实验总结分析报告:从系统的角度分析影响程序执行性能的因素

标签:冯诺依曼   opera   word   linux操作   汇编   函数调用   cal   次数   void   

原文地址:https://www.cnblogs.com/atimc/p/14770883.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!