zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【操作系统导论】机制:受限直接执行 | 中断处理 | 陷阱 | 协作方式 | 非协作方式 | 上下文切换

执行操作系统 处理 方式 机制 切换 直接 中断
2023-09-14 09:15:59 时间

💭 写在前面

本系列博客为复习操作系统导论的笔记,内容主要参考自:

  • Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau, Operating Systems: Three Easy PiecesA. Silberschatz, P. Galvin, and G. Gagne,
  • Operating System Concepts, 9th Edition, John Wiley & Sons, Inc., 2014, ISBN 978-1-118-09375-7.Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

目录

0x00 如何通过控制有效地虚拟化CPU?(How to Efficiently Virtualize the CPU with Control)

0x01 受限直接执行(Direct Execution)

0x02 进程创建(Process Creation)

0x03 直接运行会不会翻车?(Any Problems in Direct Execution)

0x04 中断处理(Interrupt Handling)

0x05 双模式操作(Solution for Problem 1: Dual Mode Operation)

0x06 系统调用及其整体流程(System Call and Its Overall Flow)

0x07 实施系统调用(System Call Implementation)

0x08 系统调用传参(System Call Parameter Passing)

0x09 代码如何在陷阱中运行(What Code to Run in Trap)

0x0A 问题2解决方案:协作方式(Cooperative Approach)

0x0B 问题2的解决方案:非协作方式(Non-Cooperative Approach)

0x0C 上下文切换:保存和恢复上下文(Context Switch: Saving and Restoring Context)

0x0D 担心并发么?(Worried About Concurrency? )

* 0X0E  Example in Pintos (User Side)


0x00 如何通过控制有效地虚拟化CPU?(How to Efficiently Virtualize the CPU with Control)

在上一章中我们讲了虚拟化CPU,操作系统需要以某种方式让许多任务共享物理 CPU,让他们看起来像是同时运行。它的基本思想很简单:运行一个进程一段时间,然后运行另一个进程,如此轮换。这种方式我们称之为时分共享(time sharing),通过时分共享CPU,就实现了虚拟化。

❓ 关键问题:如何高效地、可控地虚拟化 CPU?

💡 答案:The OS needs to share the physical CPU by time sharing.  (操作系统共享CPU需要通过 时分共享

然而构建这样地虚拟化机制存在一些挑战:

  • Performance(性能):如何在不增加系统开销的情况下实现虚拟化?
  • Control(控制):如何有效的运行进程,同时保留对 CPU 的控制?如果没有控制权,一个进程可以简单地无限制地运行并接管机器,或访问没有权限的信息。

因此,在保持控制权地同时谋取高性能,这是构建操作系统的主要挑战之一!

0x01 受限直接执行(Direct Execution)

只需直接在 CPU 上运行程序即可:

Without limits on running programs, the OS wouldn’t be in control of anything and thus would be " just a library" (如果对运行程序没有限制,操作系统将无法控制任何事情,因此会沦落为 "仅仅是一个库")。

"对于一个有抱负的操作系统而言,这真是个令人悲伤的故事!"

0x02 进程创建(Process Creation)

1. The OS loads a program code into memory, into the address space of the process → becomes a process.

  • Programs initially reside on disk in executable format (e.g, a.out)
  • The OS perform the loading process lazily (惰性).
    • Loading pieces of code or data only as they are needed during program execution → called demand paging or demand segmentation (will be covered later).

2. The program’s run-time stack is allocated.

  • Use the stack (or registers) for local variables, function parameters, and return address.
  • Initialize the stack with arguments → argc and the argv array of main() function.

3. The program’s heap is created.

  • Used for explicitly requested dynamically allocated data.
  • Program request such space by calling malloc() and free it by calling free().

4. The OS does some other initialization tasks.

  • Input/Output (I/O) setup.
    • Each process by default has three open file descriptors.       
    • Standard input (STDIN), output (STDOUT) and error (STDERR).

5. The OS starts the program running at the entry point, namely main().

The OS transfers control of the CPU to the newly-created process

0x03 直接运行会不会翻车?(Any Problems in Direct Execution)

问题隐患 #1 : Restricted Operations(受限制的操作)

  • 如果希望执行某种受限操作,比如:
    • Issuing an I/O request to a disk(像磁盘发出 I/O 请求)
    • Gaining access to more system resources such as CPU or memory. (获得更多的CPU或内存资源)
  • 我们是否可以让所有进程做他想做的事情?  → User can do the wrong thing 

问题隐患 #2 : Switching Between Processes(在进程之间切换)

从 CPU 那获得控制权并不容易,为什么?看看下面的死循环,薯条吃到撑。

i = -1 ;
while ( i < 0 )
    整点薯条

0x04 中断处理(Interrupt Handling)

Interrupt transfers control to the interrupt service routine (or interrupt handler), through the interrupt vector, which contains the addresses of all the service routines (generally stored in low memory).  (中断通过中断向量将控制权转移给中断服务程序(或中断处理程序),该向量包含所有服务程序的地址(通常存储在低内存中))

Interrupt handler is generally a part of the operating system. (中断处理程序通常是操作系统的一部分)

Interrupt architecture must save the address of the interrupted instruction. (中断架构必须保存被中断指令的地址)

A trap(陷阱)(or an exception) is a software generated interrupt caused either by an error or a user request.

0x05 双模式操作(Solution for Problem 1: Dual Mode Operation)

Dual-mode operation allows OS to protect itself and other system components. (双模式操作允许操作系统保护自身和其他系统组件)

  • user mode(用户模式) and kernel mode(内核模式) (supervisor mode / system mode / privileged mode).

Some instructions designated as privileged(特权), are only executable in kernel mode. 

  • A process in user mode can’t issue privileged operations (such as I/O requests). If it does, the processor raises an exception and the OS would kill the process. 在用户模式下运行代码会受到限制,例如:在用户模式下不能发出 I/O 请求,这样做处理器会引发异常,操作系统可能会终止进程)

System call changes mode to kernel, return from call resets it to user.

  • The system call functions internally invoke trap (interrupt) instruction and the OS codes invoke return from trap instruction to change mode. 

The mode is managed via hardware mode bit.

  • Provides ability to distinguish when system is running user code or kernel code

0x06 系统调用及其整体流程(System Call and Its Overall Flow)

Allow the kernel to carefully expose(谨慎的控制) certain key pieces of functionality to user program, such as …  (因此内核必须谨慎的控制在陷阱上执行的代码)

  • Accessing the file system, creating and destroying processes, communicating with other processes, allocating more memory etc (访问文件系统、创建和销毁进程、与其他进程通信、分配更多内存等)

举个例子:Windows/Unix 系统调用

0x07 实施系统调用(System Call Implementation)

通常情况下,每个系统调用都有一个 System call number(序列号)。

系统调用接口维护一个表(即系统调用表),并根据这些数字编制索引。根据这些数字进行索引。

系统调用接口在操作系统内核中调用预定的系统调用,并返回系统调用的状态和任何返回值。
调用者不需要知道系统调用是如何实现的,只需要遵守API(应用程序编程接口)(例如。
POSIX API 或 Win64 API,等等),并理解操作系统将作为调用的结果做什么的。操作系统接口的大部分细节被API隐藏起来,不被程序员发现。由运行时支持库管理(一组内置于编译器中的函数库的功能)

0x08 系统调用传参(System Call Parameter Passing)

Three general methods are used to pass parameters to the OS. (有三种将参数传递给操作系统的方法)

  • Simplest: pass the parameters in registers. (其中最简单的就是:在寄存器中传递参数)

In some cases, there may be more parameters than the number of registers. (在某些情况下,参数的数量可能比寄存器还多)

Parameters are stored in a block or table in memory and the address of the block is passed as a parameter in a register. (参数存储在内存中的块或表中,块的地址作为参数传递到寄存器中)

Parameters are placed or pushed onto the stack by the program and popped off the stack by the operating system. (参数由程序放置或压入堆栈,并由操作系统从堆栈中弹出)

Block and stack methods do not limit the number or length of parameters being passed. (块和栈方法不限制传递的参数的数量或长度)

Each OS has a different mechanism to pass parameters to the OS (called Application Binary Interface (ABI)).      (每个操作系统都有不同的机制将参数传递给操作系统(称为应用程序二进制接口 (ABI))

0x09 代码如何在陷阱中运行(What Code to Run in Trap)

Sources of trap(陷阱资源):

  • Completion of disk IO 
  • Keyboard interrupt
  • System call

Trap handler: the code to run for each interrupt number (trap number).

Trap table (IDT or Interrupt Vector Table)  

  • Contains the addresses of the trap handlers.
  • The OS informs the hardware of the locations of trap handlers.
  • The instruction to inform the location of the trap table is also privileged instruction.
  • You cannot execute this instruction in user mode.

0x0A 问题2解决方案:协作方式(Cooperative Approach)

操作系统如何重新获得 CPU 的控制权(regain control),以便它可以在进程之间切换?

💡 Cooperative (or non-preemptive) approach(协作方式):Wait for system calls(等待系统调用)

Processes periodically give up the CPU by making system calls such as yield.

  • The OS decides to run some other task. (操作系统决定运行其他任务)
  • Application also transfer control to the OS when they do something illegal.(如果应用程序执行了某些非法操作,也会将控制转移给操作系统),比如:
    • Divide by zero(0作为除数)
    • Try to access memory that it shouldn’t be able to access(尝试访问应该无法访问呢的内存)
  • E.g. 早期版本的额 Macintosh 操作系统或旧的 Axrox Alto 系统。

A process gets stuck in an infinite loop. → Reboot the machine

(某个进程进入死循环 → 重启机器 )

0x0B 问题2的解决方案:非协作方式(Non-Cooperative Approach)

还有什么能让操作系统重新获得 CPU 的控制权(regain control),以便它可以在进程之间切换的方式?

💡 Non-cooperative (or preemptive) approach(非协作方式): The OS takes control

Use a timer interrupt(利用时间中断)

  • During the boot sequence, the OS start the timer. (在启动过程中,操作系统启动计时器)
  • The timer raise an interrupt every few milliseconds. (计时器每隔几毫秒引发一次中断)
  • When the interrupt is raised :  (当发生中断时)
    • The currently running process is suspended.(当前运行的进程将被挂起)
    • Save enough of the state of the process.(保存足够的进程状态)
    • A pre-configured interrupt handler in the OS runs(运行操作系统中预配置的中断处理程序).

A timer interrupt gives OS the ability to run again on a CPU时间中断给予了CPU重新获得控制权的权力)

0x0C 上下文切换:保存和恢复上下文(Context Switch: Saving and Restoring Context)

The state of a process such as PC, the value of the CPU registers, the process state, and memory-management information, etc. is called a context(上下文) of a process.

When CPU switches to another process, the system must save the state of the old process onto its kernel stack. and restore the saved state of the new process from the kernel stack scheduled to run. (当CPU跳转至其他进程时,系统必须将旧进程的状态保存到它的内核栈中,并从预运行的内核栈中恢复新进程的保存状态)

  • For this, the OS executes the context switch code written generally by a low-level piece of assembly code.

Context-switch time is pure overhead (i.e., system does no useful work while switching) and its speed varies from machine to machine. (上下文切换时间是纯开销(即系统在切换时不做任何有用的工作),其速度因机器不同而不同)

  • A typical speed is a several microseconds.
  • Time depends on hardware support.
    • Some processors provide multiple sets of registers, which only requires changing the pointer to the current register sets.
    • Existence of special instructions such as a single instruction to load or store all registers.

Example: xv6 上下文切换的代码

 

0x0D 担心并发么?(Worried About Concurrency? )

系统调用期间发生时钟中断时会发生什么?

处理一个系统中断时,又发生另一个中断会发生什么?这会不会让内核很难办……

这是我们下一章要讨论的并发(Concurrency)问题。

我们先来简单看看操作系统是如何解决的:

  • Disable interrupts during interrupt processing (在中断处理期间禁止中断
  • Use a number of sophisticated locking schemes to protect concurrent access to internal data structures.(操作系统还开发了许多复杂的加锁方案,以保护对内部数据的并发访问)

具体细节我们将在后面章节讲解并发时讨论!

* 0X0E  Example in Pintos (User Side)

Example: Other System Calls (src/lib/user/syscall.c)

Example: Other System Calls (src/lib/user/syscall.c)

Example: Type of System Calls in Pintos (systemcall-nr.h)

 

Example: Register System Call Handler at IDT

中断描述符表 (IDT) 是相关中断号的中断处理程序位置的表。

  • 在中断 0x30 (src/userprog/syscall.c) 处注册系统调用处理程序。
  • 这是在 Pintos 启动时完成的。

 

Example: write() Flow in Pintos (Kernel Side)

Example: Implementation of write() (src/filesys.c) 

 


📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2022.9.20
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

Remzi H. Arpaci-Dusseau and Andrea C. Arpaci-Dusseau, Operating Systems: Three Easy Pieces

A. Silberschatz, P. Galvin, and G. Gagne,

Operating System Concepts, 9th Edition, John Wiley & Sons, Inc., 2014, ISBN 978-1-118-09375-7.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.