linux操作系统分析-课程学习报告总结

前言

  请您根据本课程所学内容总结梳理出一个精简的Linux系统概念模型,最大程度统摄整顿本课程及相关的知识信息,模型应该是逻辑上可以运转的、自洽的,并举例某一两个具体例子(比如读写文件、分配内存、使用I/O驱动某个硬件等)纳入模型中验证模型。谈谈您对课程的心得体会,改进建议等。

 

一、计算机系统的基本工作原理

1.计算机的三个关键性方法机制

  1.1当代所有计算机平台的基础--冯诺伊曼机

    先了解一下什么是存储程序计算机?

      主要思想是讲程序存放在计算机存储器中,然后按照存储器中的存储程序的首地址执行程序的第一条指令,按照该程序中编写好的指令执行,直至程序结 束。

    冯诺伊曼机的三大特点:

      包含运算器、存储器、控制器、I/O

      内部采用二进制来表示指令和数据。

      将编写好的程序和数据先放入计算机中,然后启动。

    核心是存储程序计算机。

  1.2堆栈

    作用:记录调用框架,传递参数,保存返回值,暂时存储局部变量    

    相关寄存器:ESP+EBP(堆栈相关寄存器),CS:EIP(函数调用相关),EAX(返回值地址),还有传递参数相关

    运行机制:通过pop,push两种操作,结合以上各种寄存器,实现函数调用,返回地址的记录,并且在函数调用完之后可以返回到原文中继续执行。

  1.3中断--系统调用(这里只写相关部分的中断内容)

    系统调用的总过程:

      触发系统调用时,用户态使用int$0x80指令触发中断,跳转到汇编代码system_call,触发中断机制,当前进程用户态的堆栈SS:ESP,CS:EIP EFLAGS保存在内核中,接下来执行到system_call的位置,将这段汇编用于保存现场,执行系统调用内核函数,函数调用完之后返回,恢复现场。最后iret将关键现场恢复到对应的寄存器中去,并回到int$0x80之后的下一条指令继续执行。

    初始化过程:  

      系统加载 start_kernel 开始,调用了 trap.c 中的 trap_init()函数对中断进行初始化。并且调用同一文件下的set_trap_gate()/set_system_gate()/set_intr_gate()等对中断描述符进行初始化。在进入保护模式之前, IDT 再次通过 setup_idt()函数进行初始化,在这里使用了 ignore_int()函数,是为了保护未初始化完成时发生异常不出错。然后调用 init_IRQ()函数,把中断描述附表的中断处理代码段地址设在在 interrupt 数组中,该数组指向同一个函数处理 common_interrup。    

    为什么需要分级?

      系统体系架构分为用户态和内核态,用户态的权限低于核心态,也就是说代码掌控的范围收到了限制,如果没有权限级别的划分,程序员所有代码都可以使用特权指令,系统很容易出现崩溃的情况。

    

二、操作系统实现的功能之一-进程管理

  1.进程的的概念:

    运行一个程序的时候,操作系统需要描述其的运行过程,通过结构体task_struct{}来描述,统称为PCB。

  2.进程的描述信息有:

    PID,进程状态,优先级,sp,上下文,内存指针。

  3.创建进程--fork()

    fork函数不同于其他函数,因为其返回次数的特殊性:fork会有两个返回值,一个为父亲进程的返回值,一个为子进程的

    子进程返回0,父进程返回子进程的进程ID。

  4.fork运行机制:

    触发系统调用时,用户态使用int$0x80指令触发中断,跳转到汇编代码system_call,触发中断机制后把当前进程用户态的堆栈SS:ESP,CS:EIP EFLAGS,接下来执行到system_call的位置,将这段汇编用于保存现场,执行系统调用内核函数,函数调用完之后返回,恢复现场。最后iret将关键现场恢复到对应的寄存器中去,并回到int$0x80之后的下一条指令继续执行。

    fork系统调用创建了一个子进程,子进程复制了父进程中所有的进程信息(内核堆栈,进程描述符),但有些信息是不一样的,比如pid和内核堆栈,还有将新的进程连接到各种链表中,要保存进程执行到哪个位置,父子进程共享存储空间。

  5.相关函数:

    fork,vfork,和clone3个系统调用和kernel_thread内核函数都是通过do_fork()来创建进程的。

    

  6.进程状态:

    阻塞态,运行态,就绪态。

  7.进程调度策略:

    7.1 实时调度策略:SCHED_FIFO和SCHED_RR,实时系统的优先级是静态设定的,在就绪队列没有实时进程的情况下,普通进程才能获得调度,二者分别为先  进先出和时间片轮转。

    7.2 根据负载变化发生变化:SCHED_NORMAL,每个进程分配到的cpu时间占比有比例跟系统当前的负载有关。

  8.调度算法:

    CFS:基于权重的动态优先级调度算法,已使用的虚拟时间越少,进程排序就越靠前。

  9.进程上下文切换

    包括两个部分:切换页全局目录CR3和切换内核态堆栈和硬件上下文。

    

 

 

最后给出一个linux系统概念模型:

                   linux操作系统分析-课程学习报告总结_第1张图片

 

 举例验证:

 

    读写文件,在读写文件之前,必须使用oepn打开一个文件,打开文件首先open会执行到C库,C库里有INT $0x80指令,然后在中断向量表中找到128项,中断向量表里有中断描述符,可以找到中断处理程序入口,128项是系统调用处理函数,进入系统调用处理函数,保存现场,系统调用号存储eax中,根据系统调用号执行系统调用表中对应那一项的函数。系统调用表是相应的函数指针,这里会执行sys_open。sys_open进行命令查找,找到文件控制块,根据不同文件类型,调用文件打开函数,文件打开函数会创建一个系统文件打开表file,file的很多内容来自文件控制块,填完之后,进程也有一个进程文件打开表,这个结构里面有fd数组,fd数组是指针,找个空闲的,把它指向之前已经创建的file结构,最后返回那一项的索引号,即fd。

    当进程使用read系统调用读这个文件,就会根据fd数组的下标 找到fd数组的对应项,然后找到指向之前创建的file结构的指针,再找到这个file结构,最后找到file结构里的file_operations里的具体的read函数来读取文件。

    当进程使用write系统调用写数据到这个文件时也会根据fd数组的下标 找到fd数组的对应项,然后找到之前创建的file结构的指针,再找到这个file结构,进而找到file结构里的file_operations里的具体的write函数来写文件。

    

建议:

  课后作业全部是实验内容,以后能不能布置一些书面作业,这样对整体理解也有好处。

      

 

你可能感兴趣的:(linux操作系统分析-课程学习报告总结)