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

从系统的角度分析影响程序执行性能的因素

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

标签:RKE   系统文件   进程   针对   linux系统   file   中断   动态   系统模块   

从系统的角度分析影响程序执行性能的因素

一、实验总结分析报告要求

1、请您根据本课程所学内容总结梳理出一个精简的Linux系统概念模型,最大程度统摄整顿本课程及相关的知识信息,模型应该是逻辑上可以运转的、自洽的,
并举例某一两个具体例子(比如读写文件、分配内存、使用I/O驱动某个硬件等)纳入模型中验证模型。
2、然后将一个应用程序放入该系统模型中系统性的梳理影响应用程序性能表现的因素,并说明原因。
3、产出要求是发表一篇博客文章,长度不限,1要简略,2是重点,只谈自己的思考和梳理,严禁引用任何资料(包括本课程的资料)造成文章虚长。

二、精简的Linux系统概述

操作系统是管理计算机硬件与软件资源的计算机程序一般由内核、shell 和应用程序组成。核心是内核,控制着计算机系统上的所有硬件和软件,在必要时分配硬件,并根据需要执行软件。内核主要负责进程管理、内存管理、文件系统等。

技术图片

进程管理模块主要是对进程使用的处理机进行管理和控制。Linux以进程作为系统资源分配的基本单位,并采用动态优先级的进程高级算法,保证各个进程使用处理机的合理性。使用的调度策略有:先进先出的实时进程、时间片轮转的实时进程、普通的分时进程

内存管理模块采用了虚拟存储机制,实现对多进程的存储管理,使得每个进程都有各自互不干涉的进程地址空间。

文件系统模块采用了虚拟文件系统(VFS),屏蔽了各种文件系统的差别,为处理各种不同的文件系统提供了统一的接口,支持多种不同的物理文件系统。同时,Linux把各种硬件设备看作一种特殊的文件来处理,用管理文件的方法管理设备,非常方便、有效。

三、进程管理

在Linux内核中用一个数据结构来代表处理不同的实体,这个数据结构就是通常所说的进程描述符或进程控制块(PCB)。在linux操作系统下这个数据结构就是task_struct结构体。

1、概述

(1)进程定义:进程是由正文段(代码)、用户数据段(进程直接进行操作的所有数据, 以及进程使用的进程堆栈)和系统数据段(进程的控制信息)组成的一个动态实体。
(2)在系统数据段存放着进程控制块PCB,PCB是名为task_struct的数据结构,存放着进程的相关信息。进程创建时建立一个task_struct结构体,进程结束时销毁。
Linux在内存中专门开辟了一个空间来存放进程结构体PCB,与进程的内核堆栈一起,放在一个8KB的动态内存中,通过esp就能访问进程描述符。

*2、进程的状态*

(1)运行态、就绪态、阻塞态、创建态、终止态

技术图片

3、进程调度

(1)非剥夺方式 分派程序一旦把处理机分配给某进程后 便让它一直运行下去,直到进程完成或发生某事件而 阻塞时,才把处理机分配给另一个进程。 
(2)剥夺方式 当一个进程正在运行时,系统可以基于某 种原则,剥夺已分配给它的处理机,将之分配给其它 进程。剥夺原则有:优先权原则、短进程、优先原则、 时间片原则。
(3)进程调度算法:先进先出、最短时间优先、优先级调度算法、时间片轮转算法、

四、内存管理

linux的内存从宏观上分为内核区与用户区。内核进程可以访问所有内存,而用户进程只能访问用户区。在编写linux内核模块时,如果内核模块需要访问用户区内存,需要从用户区内存复制数据,而不是直接访问。在内存管理时,内存按段、页来分割,以方便管理。同时通过虚拟内存和硬盘空间,让所有程序共享整个内存。基于LRU的调度算法和程序的连续性规则,将长期不用的内存页面置换到硬盘上,将需要的内存页面置换到内存中,从而造成每个进程都拥有块完整内存的假象。从进程的角度看,内存分为数据段、代码段、BSS段、堆和栈。栈是进程的运行空间,代码段保存了进程的指令集合,BBS和数据段保存了进程的静态变量等,而堆用于进程动态申请内存。

五、文件管理

(1)文件系统:就是操作系统中实现文件管理的一组软件、被管理的文件以及为实施文件管理所需要的一些数据结构的总称。
(2)在Linux中一切皆文件,即在 Linux 系统中的所有东西都可以通过文件的方式访问、管理。
(3)虚拟文件系统(VFS),是 Linux 内核中的一个软件层,用于给用户空间的程序提供文件系统接口;同时,它也提供了内核中的一个抽象功能,允许不同的文件系统共存。
系统中所有的文件系统不但依赖 VFS 共存,而且也依靠 VFS 协同工作。
(4)VFS文件模型如下图:
VFS是一种通用文件模型,包含两个接口,一个与用户连接,一个与底层的文件系统层(提供具体的文件结构实现)连接。不同文件系统通过mount(挂载、安装)到根文件系统中。
用户通过VFS提供的read(),write()等系统调用操作文件,VFS调用sys_read()、sys_write()。
VFS由以下对象组成:超级块对象(存放文件系统信息)、inode对象(FCB)、文件对象(已打开文件和进程的交互信息)、目录项对象(目录与文件的链接信息)。

技术图片

文件打开和读写的流程:

  1. 进程X读写一个文件首先要使用open系统调用打开这个文件,根据给出的文件路径获取它在哪个存储设备上(FAT32格式的u盘、NTFS格式的磁盘等等),可以找到该设备对应的设备文件的文件控制块inode,inode里有对应的设备号,根据设备号可以找到对应的驱动程序。在内核初始化时已经将各个设备的设备驱动程序注册到内核,并为他们生成对应的设备文件,设备文件向上提供统一的接口如open()、read()等,方便调用。而open系统调用会新建一个file结构,并在进程X的进程打开文件表的fd数组里找到空闲的一项,指向刚创建的file结构,然后返回fd数组的下标。假如要访问的文件存储在FAT32格式的块设备上,程序员写的驱动程序包括具体的针对FAT32的读写打开关闭等函数,他们已经被注册到内核,通过设备号就能找到对应的驱动程序,然后用具体的操作函数来初始化设备文件的文件控制块inode节点里的cdev,再用inode节点的cdev初始化系统文件打开表file结构里的file_operations。以上都是open系统调用内核干的事,直观上来说就是内核向用户态返回了一个整数(fd数组的下标)。

  2. 进程X使用read系统调用读这个文件,就会根据参数:fd数组的下标 找到fd数组的对应项,进而找到指向第1步创建的file结构的指针,进而找到这个file结构,进而找到file结构里的file_operations里的具体的read函数来读取文件,这是一个从抽象到具体的过程。最后系统调用返回告诉用户态进程X读操作成功与否。

  3. 进程X使用write系统调用写数据到这个文件,就会根据参数:fd数组的下标 找到fd数组的对应项,进而找到指向第1步创建的file结构的指针,进而找到这个file结构,进而找到file结构里的file_operations里的具体的write函数来写文件,这也是一个从抽象到具体的过程。最后系统调用返回告诉用户态进程X写操作成功与否。

六、具体实例

 文件的读与写,首先文件的读/写主要是通过系统调用read ( )和write( )完成的。read( )和write( )的服务例程分别是sys_read ( )和sys_write ( )函数。它们都需要三个参数:一个文件描述符fd; 一个包含要传送数据的内存缓冲区地址buf;一个指定应该传送多 少字节数的count。read ( )把数据从文件传送到缓冲区,而 write ( )执行相反的操作;两个系统调用都返回所成功传送的字节数,或者发一个错误信号 并返回-1。读或写操作总是发生在由当前文件指针所指定的文件偏移量处。两个系统调用都通过把所传送 的字节数加到文件指针来更新文件指针。

七、将一个应用程序放入系统模型,分析影响应用程序性能表现的因素

第一个终端里运行 sysbench ,模拟系统多线程调度的瓶颈:

# 以10个线程运行5分钟的基准测试,模拟多线程切换的问题
sysbench --threads=10 --max-time=300 threads run

在第二个终端运行 vmstat ,观察上下文切换情况:

# 每隔1秒输出1组数据(需要Ctrl+C才结束)
vmstat 1
 
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa s
6 0 0 6487428 118240 1292772 0 0 0 0 9019 1398830 16 84 0
8 0 0 6487428 118240 1292772 0 0 0 0 10191 1392312 16 84

cs 列:上下文切换次数骤然上升到了 139 万
r 列:就绪队列的长度已经到了 8,远远超过了系统 CPU 的个数 2,所以肯定会有大量的 CPU 竞争
us(user)和 sy(system)列:这两列的 CPU 使用率加起来上升到了 100%,其中sy 列高达 84%
in 列:中断次数也上升到了 1 万左右,说明中断处理也是个潜在的问题。

综合这几个指标可以知道,系统的就绪队列过长,也就是正在运行和等待 CPU 的进程数过多,导致了大量的上下文切换,而上下文切换又导致了系统 CPU 的占用率升高。

在第三个终端再用 pidstat 来看一下, CPU 和进程上下文切换的情况:

# 每隔1秒输出1组数据(需要 Ctrl+C 才结束)
# -w参数表示输出进程切换指标,而-u参数则表示输出CPU使用指标
pidstat -w -u 1
 
08:06:33      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
08:06:34        0     10488   30.00  100.00    0.00    0.00  100.00     0  sysbench
08:06:34        0     26326    0.00    1.00    0.00    0.00    1.00     0  kworker/u4:2
 
08:06:33      UID       PID   cswch/s nvcswch/s  Command
08:06:34        0         8     11.00      0.00  rcu_sched
08:06:34        0        16      1.00      0.00  ksoftirqd/1
08:06:34        0       471      1.00      0.00  hv_balloon
08:06:34        0      1230      1.00      0.00  iscsid
08:06:34        0      4089      1.00      0.00  kworker/1:5
08:06:34        0      4333      1.00      0.00  kworker/0:3
08:06:34        0     10499      1.00    224.00  pidstat
08:06:34        0     26326    236.00      0.00  kworker/u4:2
08:06:34     1000     26784    223.00      0.00  sshd

从 pidstat 的输出可以发现,CPU 使用率的升高果然是 sysbench 导致的,它的 CPU 使用率已经达到了 100%。但上下文切换则是来自其他进程,包括非自愿上下文切换频率最高的 pidstat ,以及自愿上下文切换频率最高的内核线程 kworker 和 sshd。

另外可以看到,pidstat 输出的上下文切换次数,加起来也就几百,比 vmstat 的 139 万明显小了太多。

Linux 调度的基本单位实际上是线程,而场景 sysbench 模拟的也是线程的调度问题,那么,是不是 pidstat 忽略了线程的数据呢?通过运行 man pidstat ,pidstat 默认显示进程的指标数据,加上 -t 参数后,才会输出线程的指标。

在第三个终端里再加上 -t 参数,重试一下看看:

# 每隔1秒输出一组数据(需要 Ctrl+C 才结束)
# -wt 参数表示输出线程的上下文切换指标
pidstat -wt 1
 
08:14:05      UID      TGID       TID   cswch/s nvcswch/s  Command
...
08:14:05        0     10551         -      6.00      0.00  sysbench
08:14:05        0         -     10551      6.00      0.00  |__sysbench
08:14:05        0         -     10552  18911.00 103740.00  |__sysbench
08:14:05        0         -     10553  18915.00 100955.00  |__sysbench
08:14:05        0         -     10554  18827.00 103954.00  |__sysbench

现在就能看到虽然 sysbench 进程(也就是主线程)的上下文切换次数看起来并不多,但它的子线程的上下文切换次数却有很多。上下文切换罪魁祸首,还是过多的sysbench 线程。

八、致谢

本学期上了孟老师与李老师的Linux操作系统课程,收益颇丰,对Linux操作系统的系统调用、中断处理、进程管理、进程切换、文件系统等知识,在系统内部是如何实现的有了更为深刻的理解。之前虽然有学过操作系统,但是对很多概念还是模糊不清,这很大原因是因为缺乏实践, 通过完成两位老师的几个实验,让我对操作系统的理解更加深入。
最后,真诚感谢孟宁老师和李春杰老师这一学期的辛勤付出。

从系统的角度分析影响程序执行性能的因素

标签:RKE   系统文件   进程   针对   linux系统   file   中断   动态   系统模块   

原文地址:https://www.cnblogs.com/huangmingwang/p/14782166.html

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