课程学习总结报告

课程学习总结报告

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

谈谈您对课程的心得体会,改进建议等。

产出要求是发表一篇博客文章,长度不限,只谈自己的思考,严禁引用任何资料造成文章虚长。

 

一、Linux基本工作原理

计算机的基本原理是存储程序和程序控制。预先要把指挥计算机如何进行操作的指令序列(称为程序)和原始数据通过输入设备输送到计算机内存贮器中。每一条指令中明确规定了计算机从哪个地址取数,进行什么操作,然后送到什么地址去等步骤。

OS的正常工作依赖于存储程序原理、堆栈、中断三个部分。

linux内核从一个初始化上下文环境的函数开始执行,即start_kernel函数,创建多个进程或者fork(创建一个与原来进程几乎完全相同的进程)若干进程,我们为每个进程维护一个进程描述和以及进程间的关系PCB。

当中断发生的时候,如mykernel中就是时钟中断发生之后,接下来OS就会为各进程进行调度,利用Swich_to函数在调度队列中选取出一个适合的进程(系统会根据中断向量号来调用相应的中断异常程序)。由CPU和内核堆栈保存当前进程的各寄存器信息(CPU要做两件工作,一是将当前的eip和esp压入到当前进程的内核栈,二是将esp指向当前进程的内核栈,并将eip指向中断处理入口,进入到内核态。),将eip指向要调度的进程执行的代码区,开始执行。

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

操作系统三个法宝:存储程序计算机、函数调用堆栈、中断机制。

操作系统两把宝剑:中断上下文、进程上下文的切换

中断:多道程序设计,可以多个程序同时运行,当一个中断发生时,由CPU和内核代码共同实现了保存现场和恢复现场。

 

 

 

操作系统核心功能:进程调度和中断机制,通过与硬件的配合实现多任务处理,再加上上层应用软件的支持,最终变成可以使用户可以很容易操作的计算机系统。

进程切换:当正在运行的进程等待其他的系统资源时,Linux内核将取得CPU的控制权,并将CPU分配给其他正在等待的进程。进程切换机制中包含esp的切换、堆栈的切换。

其中进程切换是操作系统最主要的功能。

进行进程切换就是从正在运行的进程中收回处理器,然后再使待运行进程来占用处理器。这里所说的从某个进程收回处理器,实质上就是把进程存放在处理器 的寄存器中的中间数据找个地方存起来,从而把处理器的寄存器腾出来让其他进程使用。让进程来占用处理器,实质上是把某个进程存放在私有堆栈中寄存器的数据(前一次本进程被中止时的中间数据)再恢复到处理器的寄存器中去,并把待运行进程的断点送入处理器的程序指针PC,于是待运行进程就开始被处理器运行了,也就是这个进程已经占有处理器的使用权了。在切换时,一个进程存储在处理器各寄存器中的中间数据叫做进程的上下文,所以进程的切换实质上就是被中止运行进程与待运行进程上下文的切换。

三、系统调用

 

 

 

中断分外部中断(硬件中断)和内部中断(软件中断),内部中断⼜称为异常(Exception),异常⼜分为故障(fault)和陷阱(trap)。

系统调就是利陷阱(trap)这种软件中断式主动从户态进内核态的。

 

 

 

系统调用时执行的操作:
1)在进程的内核态堆栈中保存大多数寄存器的内容(即保存恢复进程到用户态执行所需要的上下文)
2)根据用户态传递的系统调用号,确定系统调用的服务例程
3)调用名为系统调用服务例程的相应的C函数来处理系统调用
4)从系统调用返回

系统调用的执行过程:在用户态下执行某个API函数,在API函数中有一个int 0x80的中断向量,触发后,由用户态进入内核态,保存现场,查找system_ call表找到相应的系统调用号,找到后执行相应的系统调用服务例程,执行过后返回,恢复现场,回到用户态。

 

 

 

四、进程描述和进程创建

关于进程的描述和创建,主要包括PCB的组织形式、进程的数据结构进程描述符、fork系统调用的关键执行过程。

操作系统三大功能:进程管理(核心)、内存管理、文件系统

PCB task_struct中包含:进程状态、进程打开的文件、进程优先级信息

进程控制块PCB——进程描述符task_stuck提供了内核所需了解的进程信息

进程的创建:start_kernel …cpu_idle –>kernel_init和kthreadd –>0、1、2号进程(其中0号是所有进程的祖先,1号进程是所有用户线程的祖先,2号进程是所有内核线程的祖先)

fork中断上下文切换:

    从父进程的角度看,fork的执行过程跟一般的系统调用一样:⽤户态有⼀个int $0x80或syscall指令触发系统调⽤,跳转到系统调⽤⼊⼝的汇编代码。int $0x80指令触发entry_INT80_32并以iret返回系统调⽤,syscall指令触发entry_SYSCALL_64并sysret或iret返回系统调⽤。系统调⽤陷⼊内核态,从⽤户态堆栈转换到内核态堆栈,然后把相应的CPU关键的现场栈顶寄存器、指令指针寄存器、标志寄存器等保存到内核堆栈,保存现场。系统调⽤⼊⼝的汇编代码还会通过系统调⽤号系统调内核处理函数,最后恢复现场和系统调⽤返回将CPU关键现场栈顶寄存器、指令指针寄存器、标志寄存器等从内核堆栈中恢复到对应寄存器中,并回到⽤户态int $0x80或syscall指令之后的下⼀条指令的位置继续执⾏。

fork进程上下文切换:

    fork创建了一个子进程,涉及进程的上下文切换:⼦进程复制了⽗进程中所有的进程上下文信息,包括内核堆栈、进程描述符等,进程作为个独的进程也会被调度。

    当⼦进程获得CPU开始运⾏时,它是从哪⾥开始运⾏的呢?从⽤户态空间来看,就是fork系统调的下条指令(参见上面小程序的输出结果)。

    但fork系统调⽤在⼦进程当中也是返回的,也就是说fork系统调⽤在内核⾥⾯变成了⽗⼦两个进程,⽗进程正常fork系统调⽤返回到⽤户态,fork出来的⼦进程也要从内核⾥返回到⽤户态。

    对于进程来讲,fork系统调在内核处理程序中是从何处开始执的呢?

    创建⼀个进程是复制当前进程的信息,就是通过_do_fork函数来创建了⼀个新进程。⽗进程和⼦进程的绝⼤部分信息是完全⼀样的,但是有些信息是不能⼀样的,⽐如 pid 的值和内核堆栈。还有将新进程链接到各种链表中,要保存进程执⾏到哪个位置,有⼀个thread数据结构记录进程执⾏上下⽂的关键信息也不能⼀样,否则会发⽣问题。fork⼀个⼦进程的过程中,复制⽗进程的资源时采⽤了Copy OnWrite(写时复制)技术,不需要修改的进程资源⽗⼦进程是共享内存存储空间的。

 

 

 

五、可执行程序的装载

主要包括得到一个可执行程序过程、ELF文件格式的结构和静态链接、可执行程序的静态加载过程和动态加载过程

链接器的两个任务:符号解析、重定位

目标文件的三种形式:可重定位目标文件(编译器和汇编器可生成)、可执行目标文件(链接器可生成)、共享目标文件(编译器和汇编器可生成)

新的可执行程序起点——一般是地址空间为0x8048000或0x8048300

execve执行静态链接程序时,通过修改内核堆栈中保存的eip的值作为新进程的起点

动态连接有两种形式:可执行程序装载时动态连接和运行时动态链接

do_ execve

do_ execve调用do_ execve_ common,do_ execve_ common主要依靠exec_ binprm,其中重要的函数:search_binary_handler(bprm)。

新的可执行程序是从new_ip开始执行,start_thread实际上是把返回到用户态的位置从Int 0x80的下一条指令,变成了规定的新加载的可执行文件的入口位置,即修改内核堆栈的EIP的值作为新程序的起点。

当一个进程准备执行到execve系统调用前,该进程会首先fork出一个子进程,然后由子进程去执行execve系统调用,陷入内核态,用execve加载的可执行文件会覆盖当前子进程的可执行程序,相当于进程找了个替罪羔羊,自己逍遥法外。当execve系统调用返回时,返回新的可执行程序的执行起点,execve系统调用返回后新的可执行程序能顺利执行。

对于静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时,如果是静态链接,elf_entry指向可执行文件规定的头部(main函数对应的位置0x8048***);如果需要依赖动态链接库,elf_entry指向动态链接器的起点。动态链接主要是由动态链接器ld来完成的。

 

六、Linux系统的一般执行过程

最一般的情况:正在运行的用户态进程X切换到运行用户态进程Y的过程

    1、正在运行的用户态进程X

    2、发生中断——

                          (CPU自动完成)

                           save cs:eip/esp/eflags(current) to kernel stack

                           load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack).

    3、SAVE_ALL //保存现场

    4、中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换

    5、标号1之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行)

    6、restore_all //恢复现场

    7、iret - pop cs:eip/ss:esp/eflags from kernel stack返回执行的是Y进程曾经发生中断时用户态的下一条指令,恢复现场,恢复不是X进程的现场,而是曾经保存的Y进程现场)

    8、继续运行用户态进程Y

 

七、驱动程序

驱动是应用软件和硬件的桥梁它使得应用软件只需要调用系统软件的应用编程接口(API)就可让硬件去完成要求的工作。驱动程序沟通着硬件和应用软件,而驱动工程师沟通着硬件工程师和软件工程师。

Linux将硬件设备看作一个特殊的文件来操作,该文件被称为设备文件;系统通过对设备文件的读写等操作,实现对外设的读写等操作

驱动程序是设备文件与直接外设间的桥梁

Linux系统使用设备号来标识设备文件。设备号分为主设备号和从设备号。

主设备号是同一类设备的标识,对应着一个驱动程序

从设备号是在驱动程序中来指示某个物理设备的实例,从设备号使得不同的物理实例可以使用同一个驱动程序

 

 八、文件系统

文件系统,就是操作系统中实现文件统一管理的一组软件、被管理的文件以及为实施文件管理所需要的一些数据结构的总称。

FCB是文件存在的标志,它记录了系统管理文件所需要的全部信息。

在Linux中文件控制块称为inode

 

 

 

九、心得体会,改进建议:

  通过linux操作系统学习收获还是挺多的,了解了linux操作系统的基本原理、工作过程、中断、系统调用、进程创建执行切换、时钟、驱动管理、文件系统、进程地址空间等等。也能动手进行linux实验,通过实验进一步加深对linux系统的理解。虽然是因为疫情只能线上授课,两位老师也是非常尽心尽责。

posted @ 2020-07-09 21:31  waaq  阅读(248)  评论(0)    收藏  举报