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

Linux简述

Linux指的是Linus Torvalds维护的(及通过主要镜像⽹站发 布的)内核。

Linux操作系统的体系架构分为用户态和内核态

用户态:CPU可以执行包括特权指令在内的所有指令,可以访问内存中的所有数据,包括外围设备,如硬盘、网卡等。

内核态:CPU能够执行有限范围内的指令,只能访问用户进程中的数据,且不能访问外围设备。

Linux系统一般由4个主要部分组成:内核、shell、文件系统和应用程序。

内核、shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序、管理文件并使用系统。

Linux内核主要有以下几个功能:

  1. 进程管理:保证各个进程能够合理地利用CPU资源完成自身任务。
  2. 内存管理:管理内存资源,使得内存被进程安全使用。
  3. 文件管理:通过文件系统来组织和管理在计算机中所存储的大量程序和数据。
  4. I/O设备管理:将鼠标、键盘等外设抽象为虚拟文件,Linux内核提供诸如open、write、read等接口函数对其统一管理。

一 进程管理

操作系统内核中最核心的功能是进程管理

进程是程序在处理机上的一次执行过程,它是一个动态的概念。而程序是指令的有序集合,是一个静态的概念。

进程的上下文(context)包括进程的状态、有关变量和数据结构的值、机器寄存器的值和PCB以及有关程序、数据等。

进程管理的核心功能大致分为四类:控制,同步,通信,调度。内核通过 SCI 提供了一个应用程序编程接口(API)来创建一个新进程(fork、exec),停止进程(kill、exit),并在它们之间进行通信和同步(signal )。

进程的状态大体上分为:可运行态、暂停态、等待态/等待态、僵死态。

当正在执行的进程由于某种原因要让出处理机时,系统要做进程上下文切换,以使另一个进程得以执行。

进程调度的时机:

  1. 进程状态发生变化时
  2. 当前进程时间片用完时
  3. 进程从系统调用返回到用户态时
  4. 中断处理后,进程返回到用户态时

Linux进程调度

Linux的进程调度是基于优先级的调度。Linux的进程分为普通进程和实时进程,在基于优先级的算法下实时进程的优先级高于普通进程。Linux中进程的优先级是动态的,调度程序周期性的调整他们的优先级,避免进程饥饿。调度策略:
  
  SCHED_OTHER 非实时进程,基于优先级的轮转法

  SCHED_FIFO 实时进程,基于先进先出算法

  SCHED_RR 实时进程,基于优先权的轮转法
  
  在可运行队列结构中,arrays数组的两个元素分别用来表示活动进程集合过期进程集合,active和expired两个指针分别直接指向这两个集合。活动进程:处于可运行状态的进程,并且还没有用完他们的时间片,他们等待被运行。过期进程:处于可运行状态的进程,但已经用完了自己的时间片,在其他进程没有用完它们的时间片之前,他们不能再被运行。

二 中断处理

中断分外部中断(硬件中断)和内部中断(软件中断)。内部中断⼜称为异常(Exception),异常⼜分为故障(fault)和陷阱(trap)。中断(广义)会改变处理器执行指令的顺序,通常与CPU芯片内部或外部硬件电路产生的电信号相对应。中断是异步的:由硬件随机产生,在程序执行的任何时候可能出现;异常是同步的:在(特殊的或出错的)指令执行时由CPU控制单元产生。

系统调用作为一种特殊的中断,就是利⽤陷阱(trap)这种软件中断⽅式主动从⽤户态进⼊内核态的。

进程上下文是把系统提供给进程的处于动态变化的运行环境总和。

中断上下文它是一个内核控制路径,代表了中断发生时正在运行的进程执行。

中断的处理过程:

  1. 确定中断向量。
  2. 利用中断向量在IDT中找到对应中断门,在中断门中得到段选择符从而可以从GDT中找到中断服务例程的段基址。
  3. 确定中断发生的特权级合法(linux只有内核态和用户态两种特权级,此步用来检查中断程序的特权是否低于引起中断的程序的特权,低优先级程序不能引起高优先级程序)
  4. 检查是否发生特权级变化(用户态陷入内核态,这时候需要设置内核的堆栈),如果发生读取当前程序的tss段(通过tr寄存器读取)来选择新特权级的ss和esp指针,然后保存旧的ss和esp指针。
  5. 若发生的是故障,用引起异常的指令地址修改cs和eip寄存器的值,以使得这条指令在异常处理结束后能被再次执行。
  6. 在栈中保存eflags、cs和eip的内容。
  7. 如果异常产生一个硬件出错码,则将它保存在栈中。
  8. 装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量字段。这对寄存器值给出中断或者异常处理程序的第一条指定的逻辑地址

三、系统调用

Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。用户可以通过系统调用命令在自己的应用程序中调用它们。

系统调用和普通的函数调区别:

    系统调用由操作系统核心提供,运行于核心态;

    普通的函数调用由函数库或用户自己提供,运行于用户态;

使用系统调用:

进程是不能访问内核的。它不能访问内核所占内存空间也不能调用内核函数,但是系统调用可以。其原理是进程先用适当的值填充寄存器,然后调用一个特殊的指令,这个指令会跳到一个事先定义的内核中的一个位置。

进程可以跳转到的内核位置叫做sysem_call。这个过程检查系统调用号,这个号码告诉内核进程请求哪种服务。然后,它查看系统调用表(sys_call_table)找到所调用的内核函数入口地址。接着,就调用函数,等返回后,做一些系统检查,最后返回到进程(或到其他进程,如果这个进程时间用尽)。如果你希望读这段代码,它在<内核源码目录>/kernel/entry.S,Entry(system_call)的下一行。

四 文件系统

Linux为上层用户提供了一个统一的、抽象的界面来访问文件系统,实际的文件系统必须实现符合VFS标准的接口,才能与VFS协同工作。

  • 每次open一个文件都会创建一个file对象,如果使用dup()或fork()则一个或多个进程file_sturct的fd_array条目可以指向同一个file对象;
  • file对象中的f_op被设置成指向某个具体文件系统所系统的一组操作函数;
  • file对象中还保存了文件的读写位置,并保存了指向该文件的inode指针,将inode串成双向链表构成系统inode表。
  • 所以整体上是每个进程的文件描述符fd数组中的条目指向系统存储file对象的表,file对象指向inode表中的条目。

五 心得体会

本学期Linux操作系统分析,通过在Linux内核上的一个简单、虚拟、可编程的计算机硬件模拟环境mykernel上,我们编写了一个简单的操作系统内核、了解了操作系统内核核心功能及运行工作机;通过汇编指令触发该系统调用,跟踪系统调用的内核处理过程,系统调用入口的保存现场、恢复现场和系统调用返回以及内核堆栈状态的变化;通过中断上下文的切换分析了Linux系统的一般执行过程。通过这门课程,我发现编写一个Linux内核并不困难,这使我对编程的学习又多了几分信心。同时对Linux操作系统有了更深入的了解。希望老师在讲课的时候可以再多介绍一些基础知识,在做课程实验的时候有些步骤零基础的同学做起来还是有些困难。但是感觉老师门讲课都很不错,语言通俗易懂,适合零基础同学入门学习。

原文地址:https://www.cnblogs.com/lidodo/p/13275660.html