Linux操作系统分析课程总结报告

 

1.总结报告要求

       根据本课程所学内容总结梳理出一个精简的Linux系统概念模型,最大程度统摄整顿本课程及相关的知识信息,模型应该是逻辑上可以运转的、自洽的,并举例某一两个具体例子(比如读写文件、分配内存、使用I/O驱动某个硬件等)纳入模型中验证模型。重点是将一个应用程序放入该系统模型中系统性的梳理影响应用程序性能表现的因素,并说明原因。

2.Linux系统概念模型

       经过本课程的学习,让我对linux系统有了更深的理解。首先一个精简的linux系统概念模型肯定要包括应用程序,系统调用及中断,进程以及内存管理,文件及设备驱动。

        对于这几个部分,我谈谈我的理解。首先linux分为用户态和内核态,主要目的为了防止用户程序随意的访问和修改内核数据。

        用户程序对于一个linux系统来说,用户程序是必不可少的,linux系统的目的就是为用户程序服务,并合理的分配及管理资源。用户程序平时运行于用户态,那么当它想要访问内核资源时怎么进入内核态呢?那就是通过系统调用或中断。

       系统调用和中断:系统调用就是用户程序与内核的桥梁,当需要时,用户程序可以主动执行陷入指令进入内核态。通过深入了解系统调用的实验,学习了触发系统调用的方式可以是调用标准函数库或者通过嵌入式汇编直接触发,以及系统调用寄存器传参的方式。而中断作为进程被动进入内核态的方式,其主要目的为了快速响应外部设备的请求,其中最重要的就是中断的上下文依靠于当前进程的上下文。

       进程和内存管理:多任务和更加复杂和占内存的用户程序的存在,进程和内存管理尤为重要。本课程我印象最深刻的就是进程切换,通过mykernel的实验,更加理解了关于进程的控制块结构以及进程切换时内核堆栈的切换和进程状态的保存,其中较为重要的是一个进程再次切换回来时它的指令运行点。内存管理主要了解进程的线性地址空间分配以及物理页框的管理。

       文件及设备驱动:linux秉持设备即文件的思想,对于设备的操作和文件的操作大体一致。主要包括用户文件打开表,系统文件打开表,以及linux文件系统的组织方式(主要是ext文件系统)。对于设备驱动,它可以称为内核和硬件的桥梁。其中设备驱动的开发流程较为重要,包括设备加载,卸载,设备操作结构体等定义。

       如下图是精简的linux系统概念模型:

 

举例验证模型:读写文件和驱动设备

       linux系统把设备当作文件来对待,打开一个设备的操作和打开文件类似,但也有些许不同。读写文件的话首先要执行打开文件的系统调用,一般是c库封装好的open函数,内部通过int或syscall指令触发128号中断,同时通过寄存器传递系统调用号以及参数,例如文件权限等,然后根据中断向量表找到系统调用入口函数,然后根据系统调用号来查系统调用表,执行对应系统调用函数。open系统调用主要根据文件名找到对应文件结点,同时在系统文件打开表中新增一项该文件FCB,然后找到进程文件打开表空闲的一项,指向系统打开文件表刚刚创建的file结构。最后open返回进程打开文件表的刚新增这一项的索引。读写操作就直接通过该索引很方便的操作对应的文件结点。

       设备驱动主要需要我们手动编写设备装载,卸载,及设备操作结构体。设备驱动主要不同就是需要将dev设备驱动结构体和使用该设备驱动的不同设备文件结点绑定,然后把设备驱动结构体中的file_operation与系统打开文件表中对应指针绑定。最后对设备操作就很方便的通过f_op来找到对应的操作函数。

3.在该模型中分析设计的应用程序

#include <unistd.h>
using namespace std;
#define number 10000
void init(int *int_array) {
    for (int i = 0; i < number; i++) {
        int_array[i] = i;
    }
}
void mutip(int *int_array, long &sum) {
    for (int i = 0; i < number; i++) {
        sum += int_array[i];
         usleep(10);
    }
}
int main() {
    int int_array[number];
    init(int_array);
    long sum = 0;
    mutip(int_array, sum);
       return 0;
}

       该程序的目的是求数组各元素之和,同时在每次求和之后加上库函数usleep延时操作。结合上述的精简linux概念模型,影响该程序性能表现的因素如下:

1.在shell中运行用户程序前要通过execve系统调用来加载可执行程序,把该程序由磁盘中加载到内存中,那磁盘的加载速度是一个重要因素。如果只考虑运行速度的话,同时静态链接的程序加载速度和运行速度也比动态链接较快。静态链接加载时不需要加载动态链接器,对于动态链接来说,若是运行时加载,则还需要利用动态链接器来加载动态加载动态链接库。

2.cache miss和缺页异常。一个好的程序应尽可能满足局部性原理,尽量满足较低的cache缺失率。上述该程序求数组各元素之和,数组容量大于cache容量,频繁的cache缺失也是一个重要的性能制约因素。这可以利用perf工具进行具体的性能分析。如下图:

3.进程上下文切换。该程序中执行了库函数usleep延时函数,usleep函数会触发nanosleep系统调用,会把当前执行进程挂起,do_nanosleep把定时器队列上加入一个hrtimer型定时器。在定时器时间计时完成,会触发进程调度切换。进程切换时要保存进程的上下文,通过调度器在就绪队列调度就绪进程,然后进行内核堆栈的切换。此点也可由火焰图观察出来,火焰图y 轴表示调用栈,顶部就是正在执行的函数,下方都是它的父函数。x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。只要有"平顶",就表示该函数可能存在性能问题。如下图所示进程切换占据了大部分运行时间。

4.硬件制约。主要包括cpu性能,当前的利用率,指令流水线的级数,内存的大小。利用perf top可以观测出当前cpu的使用情况。

 

 

 

 

 

 

 

posted @ 2021-05-11 16:04  没能忘记  阅读(73)  评论(0)    收藏  举报