Linux实验总结分析报告
Linux体系架构
Linux操作系统主要涉及⽂件管理、内存管理、进程管理、系统中断等等。进程管理
Linux进程的存在两种运⾏模式,在Linux⾥,⼀个进程既可以运⾏⽤户程序,⼜可以运⾏操作系统程序。当进程运⾏⽤户程序时,称其为处于“⽤户模式”;当进程运⾏时出现了系统调⽤或中断事件,转⽽去执⾏操作系统内核的程序时,称其为处于“核⼼模式”。 在Linux⾥处理机就具有两种运⾏状态:核⼼态和⽤户态。Linux下进程概念及特征:
(1)、在Linux⾥,把进程定义为“程序运⾏的⼀个实例”
(2)、进程⼀⽅⾯竞争并占⽤系统资源(⽐如设备和内存),向系统提出各种请求服务;进程另⼀⽅⾯是基本的调度单位,任何时刻只有⼀个进程在CPU上运⾏。
Linux进程实体的组成:Linux中,每个进程就是⼀个任务(task),⼀般具有以下四个部分: (1)进程控制块(在Linux⾥,也称为进程描述符。)。 (2)进程专⽤的系统堆栈空间; (3)供进程执⾏的程序段(在Linux⾥,称为正⽂段); (4) 进程专⽤的数据段和⽤户堆栈空间
Linux的进程控制块——进程描述符 在Linux中,进程的进程描述符是⼀个结构类型的数据结构:task_struct。
进程描述符组成内容 进程标识(pid); 进程状态(state); 进程调度信息,包括调度策略(policy)、优先级别(priority和rt_priority)、时间⽚(counter)等; 接收的信号(*sig); 进程家族关系; 进程队列指针; CPU的现场保护区; 与⽂件系统有关的信息。 Linux的进程状态 Linux的进程可以有五种不同的状态
进程状态:可运⾏状态 可中断状态 不可中断状态 暂停状态 僵死状态
进程的创建与撤销:Linux中的每个进程,都有⼀个创建、调度运⾏、撤销死亡的⽣命期。 Linux系统中的各个进程,相互之间构成了⼀个树型的进程族系。
Linux的进程调度类型:在Linux中,进程调度被分为实时进程调度和⾮实时进程调度两种。
Linux进程描述符中与调度有关的字段:Linux进程描述符中,有四个字段与进程调度有关,它们是:policy、priority、rt_priority和counter。Linux的三种进程调度策略:Linux进程描述符中的policy字段,可以取三个值:SCHED_FIFO、SCHED_RR以及SCHED_OTHER。(1)SCHED_FIFO——实时进程的先进先出调度策略
(2)SCHED_RR——实时进程的轮转调度(3)SCHED_OTHER——⾮实时进程的轮转调度中断管理
中断有很多种,都是程序执⾏过程中的强制性转移,转移到操作系统内核相应的处理程序。中断在本质上都是软件或者硬件发⽣了某种情形⽽通知处理器的⾏为,处理器进⽽停⽌正在运⾏的当前进程,对这些通知做出相应反应,即转去执⾏预定义的中断处理程序(内核代码⼊⼝),这就需要从进程的指令流⾥切换出来。
中断能起到暂停当前进程指令流(Linux内核中称为thread)转去执⾏中断处理程序的作⽤,中断处理程序是与当前进程指令流独⽴的内核代码指令流。从⽤户程序的⾓度看进程调度的时机⼀般都是中断处理后和中断返回前的时机点进⾏,只有内核线程可以直接调⽤schedule函数主动发起进程调度和进程切换。
中断处理后,会检查⼀下是否需要进程调度。需要则切换进程(本质上是切换两个进程的内核堆栈和thread),不需要则⼀路顺着函数调⽤堆栈正常中断返回iret,这样就⾃然回到原进程继续运⾏了。中断的类型
硬件中断(Interrupt),也称为外部中断,就是CPU的两根引脚(可屏蔽中断和不可屏蔽中断)的电平信号。CPU在执⾏每条指令后检测这两根引脚的电平,如果是⾼电平,说明有中断请求,CPU就会中断当前程序的执⾏去处理中断。⼀般外设都是以这种⽅式通知CPU的,如时钟、键盘、硬盘等。
软件中断/异常(Exception),也称为内部中断,包括除零错误、系统调⽤、调试断点等,在CPU执⾏指令过程中发⽣的各种特殊情况统称为异常。异常会导致程序⽆法继续执⾏,⽽跳转到CPU预设的处理函数。异常分为如下3种:故障(Fault):故障就是有问题了,但可以恢复到当前指令。例如除0错误、缺页异常等。
退出(Abort):简单说是不可恢复的严重故障,导致程序⽆法继续运⾏,只能退出了。例如连续发⽣故障(double fault)。
陷阱(Trap):程序主动产⽣的异常,在执⾏当前指令后发⽣。前⾯研究的系统调⽤(int 0x80)以及调试程序时设置断点的指令(int 3)都属于这类。简单说就是程序⾃⼰要借⽤中断这种机制进⾏跳转,所以在有些书中也称为“⾃陷”。从CPU的视⾓看,其处理机制与其他中断处理⽅式并⽆区别,我们可以以系统调⽤为例以此类推到⼀般的中断机制。中断过程
CPU对于中断和异常的具体处理机制本质上是完全⼀致的,当CPU收到中断或者异常的信号时,它会暂停执⾏当前的程序或任务,通过⼀定的机制跳转到负责处理这个信号的相关处理程序中,在完成对这个信号的处理后再跳回到刚才被打断的程序或任务中。1)CPU检查是否有中断/异常信号
2)根据中断向量到IDT表中取得处理这个向量的中断程序的段选择符3)根据取得的段选择符到GDT中找相应的段描述符
4)CPU根据级的判断设定即将运⾏的中断服务程序要使⽤的栈的地址5)保护当前程序的现场
6)跳转到中断服务程序的第⼀条指令开始执⾏7)中断服务程序处理完毕,恢复执⾏先前中断的程序内存管理
物理内存就是系统硬件提供的内存⼤⼩,是真正的内存,相对于物理内存,在linux下还有⼀个虚拟内存的概念,虚拟内存就是为了满⾜物理内存的不⾜⽽提出的策略,它是利⽤磁盘空间虚拟出的⼀块逻辑内存,⽤作虚拟内存的磁盘空间被称为交换空间(Swap Space)。
作为物理内存的扩展,linux会在物理内存不⾜时,使⽤交换分区的虚拟内存,更详细的说,就是内核会将暂时不⽤的内存块信息写到交换空间,这样以来,物理内存得到了释放,这块内存就可以⽤于其它⽬的,当需要⽤到原始的内容时,这些信息会被重新从交换空间读⼊物理内存。
linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利⽤,内核会在适当的时候将物理内存中不经常使⽤的数据块⾃动交换到虚拟内存中,⽽将经常使⽤的信息保留到物理内存。
Linux系统会不时的进⾏页⾯交换操作,以保持尽可能多的空闲物理内存,即使并没有什么事情需要内存,Linux也会交换出暂时不⽤的内存页⾯。这可以避免等待交换所需的时间。
linux进⾏页⾯交换是有条件的,不是所有页⾯在不⽤时都交换到虚拟内存,linux内核根据”最近最经常使⽤“算法,仅仅将⼀些不经常使⽤的页⾯⽂件交换到虚拟内存。
交换空间的页⾯在使⽤时会⾸先被交换到物理内存,如果此时没有⾜够的物理内存来容纳这些页⾯,它们⼜会被马上交换出去,如此以来,虚拟内存中可能没有⾜够空间来存储这些交换页⾯,最终会导致linux出现假死机、服务异常等问题,linux虽然可以在⼀段时间内⾃⾏恢复,但是恢复后的系统已经基本不可⽤了。⽂件系统
在LINUX系统中有⼀个重要的概念:⼀切都是⽂件。 其实这是UNIX哲学的⼀个体现,⽽Linux是重写UNIX⽽来,所以这个概念也就传承了下来。在UNIX系统中,把⼀切资源都看作是⽂件,包括硬件设备。UNIX系统把每个硬件都看成是⼀个⽂件,通常称为设备⽂件,这样⽤户就可以⽤读写⽂件的⽅式实现对硬件的访问。这样带来优势也是显⽽易见的:UNIX 权限模型也是围绕⽂件的概念来建⽴的,所以对设备也就可以同样处理了。
Linux⽀持多种⽂件系统,包括ext2、ext3、vfat、ntfs、iso9660、jffs、romfs和nfs等,为了对各类⽂件系统进⾏统⼀管理,Linux引⼊了虚拟⽂件系统VFS(Virtual File System),为各类⽂件系统提供⼀个统⼀的操作界⾯和应⽤编程接⼝。VFS是⼀个软件层,⽤来处理与Unix标准⽂件系统相关的所有系统调⽤。 能为各种⽂件系统提供⼀个通⽤的、统⼀的接⼝。VFS的基本思想是引⼊⼀个通⽤⽂件模型,这个模型能够表⽰所有⽀持的⽂件系统。 通⽤⽂件模型有下列对象类型组成:
超级块对象(superblock object) 存放⽂件系统相关信息:例如⽂件系统控制块索引节点对象(inode object) 存放具体⽂件的⼀般信息:⽂件控制块/inode⽬录项对象(dentry object) 存放⽬录项与⽂件的链接信息
⽂件对象(file object) 存放已打开的⽂件和进程之间交互的信息:代表进程打开的⼀个⽂件每个主要对象都包含⼀个操作对象,它描述了内核针对主要对象可以使⽤的⽅法读取⽂件过程举例
以读取⽂件/var/log/message为例, ⾸先系统通过挂载信息(在超级块中,位置固定)找到根⽬录(/)的inode编号,根⽬录对应的inode是固定的。 根据根⽬录的inode编号,在inode table中找到对应的inode信息,从inode信息中找到存储根⽬录信息的⽬录块编号,根据编号找到数据块。 从⽬录块中存储的信息中,找到⽂件名(⽬录名)为var所对应的inode编号。 在inode table中找到var所对应的inode信息,从该inode信息中,找到var⽬录存放的数据块。从var数据块存储的信息中,找到log⽬录对应的inode编号。 重复上述步骤,直⾄找到message⽂件对应的inode结点,根据inode结点中记录的message⽂件内容对应的数据块,从数据块中读取内容。应⽤程序性能表现分析
应⽤程序的性能很⼤程度上跟存储⽅式和系统中断有着密切的关系,不同的存储⽅式可能有着不同的性能开销,例如对于⼀个⼆维数组,有两种⽅式进⾏数据保存,第⼀种代码主程序如下所⽰:
int Frist(){
int test[100000][100000]={0}; for(int i = 0 ; i < 100000 ; i++){ for(int j = 0 ; j < 100000 ; j++){ test[i][j] = 1; } }
return 0;}
第⼆种代码主程序如下所⽰:
int Second(){
int test[100000][100000]={0}; for(int j = 0 ; j < 100000 ; j++){ for(int i = 0 ; i < 100000 ; i++){ test[i][j] = 1; } }
return 0;}
由于数组是连续存储的,且根据Linux的内存管理机制,可以得到,第⼀种存储⽅式相对第⼆种存储⽅式拥有更少的缺页中断,从⽽拥有更少的开销,从⽽性能更好.总结
本⽂主要是对Linux系统进⾏了概述,并举例进⾏了说明分析。同时也感谢孟⽼师及李⽼师的教导,让我对Linux操作系统有了更加深刻的认识。