标签:不可 数据 机制 位置 工作原理 完成 存在 建立 处理程序
Linux之进程
概述:进程是Linux进行资源分配和调度的基本单位,进程也被看做是程序的一次执行过程,当持久化在磁盘上的二进制代码被载入内存时,Linux操作系统为其分配了用户栈和内核栈,同时使用task_struct这种数据结构对进程进行描述,task_struct是Linux操作系统感知进程存在的数据结构,具体描述了进程号,进程状态,进程的调度策略和调度信息,进程打开文件表,进程链表,父子进程的关系等信息。Linux根据这个数据结构找到进程对应的用户栈和内核栈,并根据cs,ip,ss,sp,ebp等寄存器信息,执行这个进程。
进程调度:有了进程的概念,Linux就可以执行磁盘中持久化的二进制代码了。为了提高cpu利用率,提高计算机的并发性,引入了进程的调度这个概念,这相当于Linux虚拟化了多个“平行空间”,每个进程都有自己独立的用户栈和内核栈,Linux内核根据调度策略,在一定的时机对进程进行调度。进程调度时机包括:时间片用完,中断返回,进程状态发生变化,系统调用返回。
进程的调度策略:Linux系统采用优先级调度的策略,又分成实时进程和非实时进程,实时进程指需要及时处理的进程,优先级范围是0~99。100~139是非实进程的优先级范围。实时进程的优先级高于非实时进程。同一优先级对列按FIFO或者RR(时间片轮转)进行调度。Linux进程调度采用了可运行对列机制。
进程调度之可运行对列工作原理:每个可运行对列有三个属性,进程数量,位图,进程对列,通过位图可以找到当前优先级最高的对列。可运行度量维护两个对列,活跃对列和过期对列。总是从活跃对列里根据调度策略选择一个进程执行,进程执行完毕后,如果当前进程是实时进程,则继续加入活跃对列中,如果是非实时进程的非批处理进程,则加入过期对列。如果活跃对列空,则将过期对列的内容负值到活跃对列中继续执行。这种机制的优点在于避免优先级低的进程出现饥饿的现象.
Linux之系统调用
为了屏蔽硬件操作的细节,增强系统的安全性,增强用户程序的可移植性,Linux操纵系统划分了用户态和内核态,对应的内存空间被划分成用户空间和内核空间。内核态的权限高于用户态,即内核态下,cs:ip可以指向任意位置,而用户态下,cs:ip的活动范围只能是自己的空间。为了使用户调用操作系统底层服务,如中断,时钟,异常等,需要采取一种机制,这种机制就是系统调用。
从软件的角度看,通过int 0x80指令或者syscall指令可以触发系统调用。首先,当linux进入内核态时,先保存此时的上下文环境,如果是硬件中断触发的系统调用,保存的是中断上下文,如果是用户程序触发的系统调用,保存用户进程上下文。所谓的上下文是内核保存的,用于系统调用返回的参数信息。然后,通过系统调用号,找到对应的系统调用处理函数的首地址,建立函数堆栈,修改cs:ip的值并执行处理函数。处理函数执行完毕后,根据保存的上下文信息恢复现场返回用户态。
Linux之中断
中断的作用:中断可分成外部中断和内部中断,外部中断用于处理外部设备的I/O请求,也叫做硬件中断;内部中断用于处理故障,陷入,错误。也叫做软件中断。它们的作用都是为了改变cpu当前正在运行的指令流去执行其他任务。中断机制能够提高I/O效率,系统调用就是一种特殊的中断。中断按是否可屏蔽分成可屏蔽中断和不可屏蔽中断,可屏蔽中断的向量可以通过对中断控制器的 编程来改变。
中断之硬件处理过程
中断之异常处理:异常处理有一个标准的结构,由三部分组成 1. 在内核态堆栈中保存大多数寄存器的内容 2. 调用C语言的函数 3. 通过ret_from_exception()从异常处理程序退出 。当异常发生时,如果控制单元 没有自动地把一个硬件错误代 码插入到栈中,相应的汇编语 言片段会包含一条pushl $0指 令,在栈中垫上一个空值,如果 错误码已经被压入堆栈,则没有 这条指令。然后,把异常处理 函数的地址压进栈中;函数的名字由异常处理程序名与do_ 前缀组成。 然后调用error_code,该函数的主要功能:(1)按照pt_regs结构定义的堆栈数据格式完成相应 的入栈操作,进一步完成现场的保存。(2) 把堆栈地址中的do_handler_name()函数的地址 装入edi寄存器中,并在这个位置写入fs值,使栈 结构进一步与pt_regs结构完全一致。(3) 最后执行call *%edi指令。
中断的一般处理流程
在内核态堆栈保存IRQ的值和寄存器的内容
common_interrupt: SAVE_ALL movl %esp,%eax call do_IRQ jmp $ret_from_intr
do_irq工作原理:
内封装了一个irq_desc数组,根据中断向量号找到对应的中断服务例程,全部执行一遍,判断具体哪个设备发生了中断,就执行这个设备的中断服务程序。
系统性总结
Linux的启动过程包括启动参数的传递,根文件系统的挂载,通过start_kernel完成了文件系统,中断,时钟,内存管理,设备管理等模块的初始化工作,保存了中断描述符表地址等信息,并初始化了0号进程。当调用一个程序时,首先使用execve系统调用对其进行加载,基本原理是读取命令行参数和环境变量,fork一个子进程,传递命令行参数和环境变量,如果是动态链接,内核返回到.intp处执行动态链接器进行动态链接。execve的结果就是加载一个可执行程序,这样一个基本的应用程序就能运行了。程序中可能涉及对设备的操作,linux用设备文件来感知设备,用户像使用普通文件一样打开一个设备文件,内核感知到这是一个设备文件时,就能根据设备号,找到该设备对应驱动程序,Linux将它们封装成进程打开文件表的一项并返回fd给用户,用户就能根据fd索引到对应的驱动程序进行设备的操作了。函数是可执行程序的基本功能模块,Linux使用函数调用堆栈这种机制对函数进行第调用,基本操作就是保存当成函数的ebp,用此时esp的位置作为新函数的ebp,基于原原来的空间进行函数空间生长,待切换的函数执行完毕后,切换回原函数的堆栈继续执行。进程调度是提高cpu吞吐率的一个重要措施,也是一种多任务处理的方式,Linux采取了基于优先级的调度策略,基于可运行对列进行调度。进程的调度发送生在内核态,通过schedule进行调度,调度 的结果是完成进程的切换,进程切换的基本思路就是保存原进程的cs:ip,ebp等寄存器信息,同时加载新进程的寄存器信息,完成用户堆栈和内核堆栈的切换。
上面是我对Linux工作机制的粗浅理解,没有面面俱到,但也有了一个宽泛认识。孟老师和李老师讲课认真负责,理论联系实践,深入浅出讲解了Linux的底层原理,对我以后做应用开发有很大的指导性作用,希望这门课越办越好。
标签:不可 数据 机制 位置 工作原理 完成 存在 建立 处理程序
原文地址:https://www.cnblogs.com/slm-/p/13177810.html