Linux操作系统是如何工作的?


一、操作系统工作的基础


1、存储程序计算机

1945年,美藉匈牙利科学家冯·诺依曼(J.Von Neumann)提出的,是现代计算机的理论基础。现代计算机已经发展到第四代,但仍遵循着这个原理。

存储程序和程序控制原理的要点是,程序输入到计算机中,存储在内存储器中(存储原理),在运行时,控制器按地址顺序取出存放在内存储器中的指令(按地址顺序访问指令),然后分析指令,执行指令的功能,遇到转移指令时,则转移到转移地址,再按地址顺序访问指令(程序控制)。

虽然计算机技术发展很快,但“存储程序原理”至今仍然是计算机内在的基本工作原理。自计算机诞生的那一天起,这一原理就决定了人们使用计算机的主要方式——编写程序和运行程序。

冯·诺依曼结构(John von Neumann)也就是存储程序奠定了现代计算机的基本结构,其特点是:

1)使用单一的处理部件来完成计算、存储以及通信的工作。

2)存储单元是定长的线性组织。

3)存储空间的单元是直接寻址的。

4)使用低级机器语言,指令通过操作码来完成简单的操作。

5)对计算进行集中的顺序控制。

6)计算机硬件系统由运算器、存储器、控制器、输入设备、输出设备五大部件组成并规定了它们的基本功能。

7)采用二进制形式表示数据和指令。

8)在执行程序和处理数据时必须将程序和数据道德从外存储器装入主存储器中,然后才能使计算机在工作时能够自动调整地从存储器中取出指令并加以执行。

 

2、堆栈(函数调用堆栈)机制

参见实验二报告:Linux操作系统实验二:进程的创建与可执行程序的加载

3、中断机制

中断可以很简单的形容为cpu暂停目前正在处理的任务,转而去处理新的请求处理的任务,当新任务处理完成后,再回到原来暂停的位置,继续处理原有的任务。

中断处理分硬件处理部分和软件处理部分,以下摘自李春杰老师课件:

中断和异常的硬件处理:

CPU的正常运行:

当执行了一条指令后,cs和eip这对寄存器包含了下一条将要执行的指令的逻辑地址。

在执行这条指令之前,CPU控制单元会检查在运行前一条指令时是否发生了一个中断或者异常。如果发生了一个中断或异常,那么CPU控制单元执行下列操作:

 

1,确定与中断或者异常关联的向量i(0~255)

2,读idtr寄存器指向的IDT表中的第i项

3,从gdtr寄存器获得GDT的基地址,并在GDT中查找,以读取IDT表项中的段选择符所标识的段描述符

4,确定中断是由授权的发生源发出的。

n  中断:中断处理程序的特权不能低于引起中断的程序的特权(对应GDT表项中的DPL vs CS寄存器中的CPL)

n  编程异常:还需比较CPL与对应IDT表项中的DPL

5,检查是否发生了特权级的变化,一般指是否由用户态陷入了内核态。
如果是由用户态陷入了内核态,控制单元必须开始使用与新的特权级相关的堆栈

n  a,读tr寄存器,访问运行进程的tss段

n  b,用与新特权级相关的栈段和栈指针装载ss和esp寄存器。这些值可以在进程的tss段中找到

n  c,在新的栈中保存ss和esp以前的值,这些值指明了与旧特权级相关的栈的逻辑地址

6,若发生的是故障,用引起异常的指令地址修改cs和eip寄存器的值,以使得这条指令在异常处理结束后能被再次执行

7,在栈中保存eflags、cs和eip的内容

8,如果异常产生一个硬件出错码,则将它保存在栈中

9,装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量字段。这对寄存器值给出中断或者异常处理程序的第一条指定的逻辑地址

中断和异常的软件处理:

1.       将中断向量入栈

2.       保存所有其他寄存器

3.       调用do_IRQ

4.       跳转到ret_from_intr

整个过程如下图所示:


二、操作系统是如何工作的


操作系统最重要的工作莫过于进程的管理和调度。每个进程通过一个叫做进程描述符

task_struct的数据结构进行描述,其中包含了进程所有的属性。下面描述操作系统如何进行进程间调度:

 如下图所示,当某进程A正在运行,esp寄存器指向进程A的用户栈栈顶,eip寄存器指向进程A的代码区,若进程A的时间片用完并发生中断,那么CPU要做两件工作:

(1)将当前的eip和esp压入到进程A的内核栈;

(2)将esp指向进程A的内核栈,并将eip指向中断处理入口,进入到内核态。
在进行SAVE_ALL即保存相关寄存器等之后,开始执行中断处理程序,进行的切换与调度就是发生在中断处理程序中。我们会根据相应的调度策略,选择下一个要执行的进程Next,并切换到进程Next。这里内核是通过执行switch_to函数来进行进程切换的,在switch_to中我们主要进行了进程的寄存器register和进程的内核栈stack的切换。当进程切换完以后,我们的esp就指向了进程B的内核栈,我们可以看到,在进程B的内核栈中保存着进程B被挂起以前的esp以及eip,我们进行出栈操作,则当前的eip指向进程B的代码区,而esp指向进程B的用户栈,这样通过esp和eip的的切换我们就切换到了进程B继续执行,完成了整个进程从A切换到进程B。


 switch_to()函数的代码如下:

  #define switch_to(prev,next,last) do{     \  
   unsigned long esi,edi;      \  
   asmvolatile("pushfl\n\t"  /* Saveflags */ \  
        "pushl %%ebp\n\t"     \  
        "movl %%esp,%0\n\t" /* save ESP */  \  
        "movl %5,%%esp\n\t" /* restore ESP */ \  
        "movl $1f,%1\n\t"  /*save EIP */  \  
        "pushl %6\n\t"  /*restore EIP */ \  
        "jmp __switch_to\n"    \  
       "1:\t"      \  
       "popl %%ebp\n\t"     \  
       "popfl"      \  
       :"=m" (prev->thread.esp),"=m"(prev->thread.eip), \  
        "=a" (last),"=S" (esi),"=D" (edi)   \  
       :"m" (next->thread.esp),"m"(next->thread.eip), \  
        "2" (prev), "d" (next));    \  
 } while (0)  



 

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了透彻理解linux工作机理,以及为何它在各种系统上能顺畅运行,你需要深入到内核的心脏。cpu与外部世界的所有交互活动都是由内核处理的,哪些程序会分享处理器的时间,以什么样的顺序来分享。内核不遗余力地管理有限的内存,以使数以千计的进程有效地共享系统资源。内核还精心组织数据传送,使得cpu不再受限于慢速硬盘。    《深入理解linux内核》第三版将引领你畅游内核中用到的最主要数据结构、算法和编程技巧。如果你的确想了解计算机内部的实现机理,那么作者透过现象探寻本质,提供了颇有价值的深入分析。本书针对具体的intel平台,讨论了其重要特征,逐行剖析了相关的代码片段。但是,本书涵盖的内容不仅仅局限于代码的机理,还解释了linux运作方式的理论支撑。    本书第三版涵盖linux 2.6,从中可以看到几乎内核每个子系统都有相当大的变化,首当其冲的是内存管理和块设备部分。本书集中讨论了如下内容:    内存管理,包括文件缓冲、进程交换以及直接内存访问(dma)    虚拟文件系统层和第二及第三扩展文件系统    进程创建及调度   信号、中断及设备驱动程序的主要接口   定时   内核中的同步   进程间通信(ipc)   程序执行   本书将使你熟悉linux所有的内在工作机理,但本书不仅仅是一种学术演练。你将了解到什么条件会促使linux产生最佳性能,你还会看到,linux在各种环境下如何满足进程调度、文件访问及内存管理期间系统提出的快速响应要求。本书有助于你充分展现linux系统的魅力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值