# ST-CS130: Operating Systems [![hackmd-github-sync-badge](https://hackmd.io/sZl5W01XTyCsfOZngy4IFg/badge)](https://hackmd.io/sZl5W01XTyCsfOZngy4IFg) ## Basic Concepts 操作系统起着分离运行、幻象(抽象层?)、粘合(高级)的作用 - Process - Program state - PC, reg, Execution flag, Stack - Address Space - Virtual mem <-> Physical mem - Thread - Protect - Multi - Run one another one based on virtual address on CPU - Frequently switch instead of real multiprocessing - Dual-mode - user mode and priviliged mode - Isolation ## Process Management ### Diff between thread and process - 线程共享 static 区 - 进程切换会更改 static 和 regs - 进程是线程的超集 ### Content Switch https://zh.wikipedia.org/zh-cn/%E4%B8%8A%E4%B8%8B%E6%96%87%E4%BA%A4%E6%8F%9B - low cost (compated to endless load addr and save word ) 一般来说,进程有三个状态, running, waiting, terminated 在操作系统执行的过程中,进程在进程池中等待,当一个进程在 running 的时候,可以发出 interrupt 信号,此时进程被放回 waiting 或者 terminated ![](https://i.imgur.com/l0Xy6e5.png) 而在现实的场景中,对于一块架构良好的 computer, 在 aaa ~ xxx KB 的位置有一块 RoM, 其中写入了固定数据,也就是 bootloader, 从 bootloader 启动操作系统。现代机器会用 UEFI 或者 ACPH 提供一层抽象 而对于操作系统的终止,通过一个电路将 CPU 的某个 reg (可能是 EFREG ) 改值, 寄存器归零,从而让操作系统从 PC = 0 的地方重新执行, 或者接从启动内存处通过 bootloader 重新启动 ### Thread-init 之前所说, Thread 有三个状态,在 time interupt 的时候通过检查 cpu-time-ticks 来切换 thread 的三个状态 ![](https://i.imgur.com/7aJLU5y.jpg) - 注意资源锁 - 倒数计数 - 中断 (interupt) -> context switch - thread scheduling: FIFO / ### Concurrency - Isolated and run one after another, there's no hazard and race in CPU and Address - Issues in synchronization (the order of excecution) - The operation is atomic - Run -> Choose -> Store old -> Load new - Let system et control of the CPU - yield (volunteerly) - exit it - All process will see itself as running even if the system has suspended it. ### Fork It could be better to understand by [Fork Bomb](https://zh.wikipedia.org/zh-hans/Fork%E7%82%B8%E5%BC%B9) 1)在父进程中,fork返回新创建子进程的进程ID; 2)在子进程中,fork返回0; 3)如果出现错误,fork返回一个负值; ### Creation of a New Thread - `ThreadFork()` create a new thread and places it on ready queue - Point to application routine (fcnPtr) - Pointer to array of arguments (FcnArgPtr) - Size of stack to allocate - Allocate new Stack and TCB - Initialize thr registers field - Update `PC` and `ra` - `run_new_thread()` will select this TCB and return into beginning of `ThreadRoot()` ### Concurrency - Independent Threads - Scheduling doesn't matter - Cooperating Threads - Many to one: 阻塞 / 空间利用率高 - One-to-One: 效率高,overhead大 - Many-to-Many: difficult - 2-Level Model - pthreads ### Thread Pool - alloc exsiting (pre-allocated) threads to programmes in the pool ### Atomic Operations - Mutex - Socket ### Lock lock the critical section and do the critical section, then unlock the section, so that others can access the section No one can access unless the **lock release** (when leaving) - Procesure - lock - unlock - wait if locked - Only mem r/w are atomic - Hardware support: disable the interupt (e.g. Intel 486 https://blog.csdn.net/qq_43401808/article/details/86592677) - 原子操作 - 上锁的过程也是原子的,因此需要 disable interupt ```C milklock.Acquire(); if (nomik) buymilk(); milklock.Lock(); ``` ### Create a thread ![](https://i.imgur.com/voDKA7G.png) ### Switch a thread ![](https://i.imgur.com/WczHhxj.png) - deadlock: a thread stucked in the wait list - Busy waiting - Pros: works and no race - Cons: - inefficient - Waiting thread may take cycles away from thread holding lock (no one wins!) - **Priority Inversion**: If busy-waiting thread has higher priority than thread holding lock if no progress! - Spin locks: - when leave, release the lock - ... - Semaphore - P(): wait => wait() => 等红灯 - if (>0) -1 and dosomething - V(): wake a P => signal() => 绿灯 - +1 - initialized value: how many processes run at once - 优先级捐赠: https://github.com/Yefancy/Pintos/issues/4 and https://blog.terrychan.me/2016/pintos-1-3 ### Deadlock and Starvation - Deadlock means a Starvation, starvation doesn't mean there's a deadlock - 死锁的发生是由于资源的争抢 (resource contention) #### Banker's Algorithm - Request resources: Wait - Get resources: release after a certain time ![](https://i.imgur.com/xNrirmG.png) - 记录有多少个进程 - 一共有多少资源 (e.g. `vcpu`) - 记录每个资源有多少 - 记录每个资源的总量 (const) - 记录每个进程分配了什么资源 - 记录每个进程需要什么资源 - https://zh.wikipedia.org/wiki/银行家算法 - `If Request[i] <= Need[i]: Raise ERROR` - `If Request[i] > Available[i]: Wait()` - ``` Python if Request[i] <= Available[i] : Available[i] -= Request[i]; Allocation[i] += Request[i]; Need[i] -= Request[i]; ``` - 这样可以避免死锁 (资源没有争抢),同时便于资源回收与调度 - 前提假设是,每个资源都会自我了解,否则这个系统就是不安全的 (这样排队的 (Need Matrix)就永远等不到了) ### Scheduling Algorithms ![](https://i.imgur.com/uZIOmsG.jpg) - Waiting Time - Average WaitingTime - Average Completion Time (Burst time + waiting time) - Goals - minimize Response Time - Maximize Throughput (reduce context switch) - Fair #### FIFO - The process won't be interupted, run one until done. - Non-preemptive algorithm - Convoy Effect: short process behind long process cause big avg completion time - **Bad for small jobs** #### Round-Robin - Each run a small time, do A then switch to do B - When time spilit $q$ is large, its limitation is FCFS - When $q$ is small, a hardware called Hyper Threading will support, Interleaved (CPU do context-switch and cause large overhead) - so $q$ should be a medium value - Pros: Fair, Fair and Fair - Cons: overhead for context switch, with the increasement of jobs #### Priority ![](https://i.imgur.com/wo4y8gf.png) Problem: - Starvation - Deadlock Solution: - Dynamic priorities - Adjust base-level priority up or down based on heuristics about - 意思就是长时间不动就降优先级 - [SRTF](https://en.wikipedia.org/wiki/Shortest_remaining_time) #### Multilevel Queue - queues (e.g. system processes) with own scudule - Scheduling done between the queues - fixed priority - possibility of starvation - MultiLevel Feedback Queue - a process can move between queues - ![](https://i.imgur.com/8m487oj.png) - ![](https://i.imgur.com/DMzAN6k.png) - ![](https://i.imgur.com/01cX6WD.png) #### Real-Time scheduling ## 期中复习 - basic knowleage about OS - Process (include preseduo code, Concurrency, Scheduling) ### 同步 - deadlock ```C wait(A) wait(B) // do something // release both ``` ```C wait(B) wait(A) // do something // release both ``` Then Programme A hold lock A wait B. Programme B hold B wait A. They can't cotinue. - starvation And - bound buffer - [https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem](https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem) - Readers-Writers - [https://blog.csdn.net/ValDC_Morning/article/details/73434006](https://blog.csdn.net/ValDC_Morning/article/details/73434006) - dining philosopher - [https://en.wikipedia.org/wiki/Dining_philosophers_problem](https://en.wikipedia.org/wiki/Dining_philosophers_problem) - Basic solution is use **Monitor** to **periodly** check or pick down ### Process - Create ## Address Space ![](https://i.imgur.com/0qEXiJz.png) - Seg: - 0: code - 1: data - 2: shared - 3: stack - Offset:偏移 - Base:对应的物理内存底端 - Limit:对应的物理内存顶端 - Valid/N: - Error:不能超过 Limit - Physical Address: 物理内存-虚拟内存是物理内存的抽象 - Access Error: ![](https://i.imgur.com/d7vXUKi.png) So, a 32-bit operating system means that it has the reg which len 32, and address space of a maximum $2^{32}$B ![](https://i.imgur.com/HYjZufl.png) ### Memory Sharing Using Page table to map the virtual address to the same physical address ### Multi-step Processing of a Program for Execution Compile -> Load -> Execute ### Prevent from multi-programming Use **Base_addr** and **Limit_addr** to ensure the range of vmem. ### Translation box (Memory Management Unit or MMU) converts between the two views ### B&B Method ![](https://i.imgur.com/Kmf4ly5.png) - Not every process is same size → memory becomes fragmented over time - Missing support for sparse address space - Would like to have multiple chunks/program (Code, Data, Stack, Heap, etc) - Hard to do inter-process sharing - Want to share code segments when possible - Want to share memory between processes - Helped by providing multiple segments per process ### More Flexible Segmentation - Each segment (Stack, Heap, Code, Data ...) is given region of contiguous memory - ![](https://i.imgur.com/V3hZoZP.png) - ![](https://i.imgur.com/fRJ67K4.png) ### Example ![](https://i.imgur.com/ZJD6ZpG.png) ![](https://i.imgur.com/S0PWJjf.png) ### Paging ![](https://i.imgur.com/uU0FKxU.png) ### 2-Level Paging ![](https://i.imgur.com/iIeYi1h.png) ### Multi-Level Paging ## Cacheing TLB ### PTE #### Demand Paging - Keep only active pages in memory - Place others on disk and mark their PTEs invalid #### Copy on Write - UNIX fork gives copy of parent address space to child - Address spaces disconnected after child created - How to do this cheaply - Make copy of parent’s page tables (point at same memory) - Mark entries in both sets of page tables as read-only - Page fault on write creates two copies #### Zero Fill On Demand - New data pages must carry no information (say be zeroed) - Mark PTEs as invalid; page fault on use gets zeroed page - Often, OS creates zeroed pages in background ### Caching Applied to Address Translation ![](https://i.imgur.com/4Tw2w6x.png) ## Demand Paging ## File System ### FAT ![](https://i.imgur.com/9VvlSmx.png) ### iNode