From 4163bbea02bf17b641759d3e4ab838c70bd15fd5 Mon Sep 17 00:00:00 2001 From: shen-dong Date: Mon, 12 Jun 2023 01:08:45 +0800 Subject: [PATCH 1/2] Dong Shen --- dongshen/deadlock.md | 22 ++ ...55\345\222\214\345\274\202\345\270\270.md" | 204 ++++++++++++++++++ ...14\350\275\257\344\270\255\346\226\255.md" | 29 +++ ...7\347\250\213 \350\277\233\347\250\213.md" | 169 +++++++++++++++ ...26\344\270\216\345\256\211\345\205\250.md" | 22 ++ ...13\351\227\264\351\200\232\344\277\241.md" | 16 ++ 6 files changed, 462 insertions(+) create mode 100644 dongshen/deadlock.md create mode 100644 "dongshen/\344\270\255\346\226\255\345\222\214\345\274\202\345\270\270.md" create mode 100644 "dongshen/\347\241\254\344\273\266\344\270\255\346\226\255\345\222\214\350\275\257\344\273\266\344\270\255\346\226\255 \347\241\254\344\270\255\346\226\255\345\222\214\350\275\257\344\270\255\346\226\255.md" create mode 100644 "dongshen/\347\272\277\347\250\213 \350\277\233\347\250\213.md" create mode 100644 "dongshen/\350\231\232\346\213\237\345\214\226\344\270\216\345\256\211\345\205\250.md" create mode 100644 "dongshen/\350\277\233\347\250\213\351\227\264\351\200\232\344\277\241.md" diff --git a/dongshen/deadlock.md b/dongshen/deadlock.md new file mode 100644 index 0000000..0392f13 --- /dev/null +++ b/dongshen/deadlock.md @@ -0,0 +1,22 @@ +**deadlock** is any situation in which no member of some group of entities can proceed because each waits for another member, including itself, to take action, such as sending a message or, more commonly, releasing a lock +A deadlock situation on a resource can arise only if all of the following conditions occur simultaneously in a system: +1. _Mutual exclusion:_ At least one resource must be held in a non-shareable mode; that is, only one process at a time can use the resource. Otherwise, the processes would not be prevented from using the resource when necessary. Only one process can use the resource at any given instant of time. +2. _Hold and wait_ or _resource holding:_ a process is currently holding at least one resource and requesting additional resources which are being held by other processes. +3. _No preemption:_ a resource can be released only voluntarily by the process holding it. +4. _Circular wait:_ each process must be waiting for a resource which is being held by another process, which in turn is waiting for the first process to release the resource. In general, there is a set of waiting processes, _P_ = {_P_1, _P_2, …, _P__N_}, such that _P_1 is waiting for a resource held by _P_2, _P_2 is waiting for a resource held by _P_3 and so on until _P__N_ is waiting for a resource held by _P_1._ +These four conditions are known as the _Coffman conditions_ from their first description in a 1971 article by Edward G. Coffman, Jr. +While these conditions are sufficient to produce a deadlock on single-instance resource systems, they only indicate the possibility of deadlock on systems having multiple instances of resources. + +Eliminate deadlock +1. detect cycle by dfs or cutting branches +2. try all the possible allocation patterns +detection: (find deadlocks happening)banker's algorithm +avoidance: (avoid deadlocks at most extent)resource trajectories (check point and roll back) +prevention: (remove conditions, definitely no deadlock) +1. attack circular waiting condition + 1. mutial exclusion: spool everything and hide the resources + 2. hold and wait:request all the rescources intially + 3. preemption: take resources away + 4. circular wait: order all the resources numerically +busy waiting: livelock +signal : deadlock \ No newline at end of file diff --git "a/dongshen/\344\270\255\346\226\255\345\222\214\345\274\202\345\270\270.md" "b/dongshen/\344\270\255\346\226\255\345\222\214\345\274\202\345\270\270.md" new file mode 100644 index 0000000..2f86a8d --- /dev/null +++ "b/dongshen/\344\270\255\346\226\255\345\222\214\345\274\202\345\270\270.md" @@ -0,0 +1,204 @@ +[[特权级]] +[[硬件中断和软件中断 硬中断和软中断]] +[[操作系统期末考试]] +中断是由硬件支持、软件配合做的 +中断向量表:表里面全部是jump 跳到中断处理代码的位置。 +发生中断的时候加上一个offset到表中找到jump函数,进行跳转 +### 上下文切换 +中断时期上下文为进程保持完全相同,理想情况下只需要保证寄存器的状态和内存的状态,但是缓存的状态如果发生了改变会暴露了上下文已经被切过了。 +由于上下文切换需要保证内存上下文一致,**会访问到页表**,因此上下文切换必须有**内核态**来做。 +为了减少上下文切换的开销,需要进行一些优化: +1. 一个是扫描寄存器的使用,如果是 没有用到的寄存器,就不进行load、store操作。 +2. syscall merge,如果两个syscall之间的间隔足够,可以把这段不太长的时间等待过去。 + syscall batching,就像store buffer一样,记下每一个syscall的操作,攒一个batching慢慢的做,只要保证静态分析中做的事情是相同的,就能保证这么多syscall按照原来的顺序是正确的。甚至会在内核中做一些常数传播的编译优化。 + _syscall merge的问题:_ + - 导致内核的膨胀,内核要记录太多的处理信息 + - 导致内核的安全问题,别的进程可以通过内核的信息得知别的进程的信息 + - 导致内核危害,内核要做的事情太多 + +#### 为什么需要中断/异常机制,目的是什么 + +一下特性是中断和异常分别提供的: + +- **支持cpu和设备之间的并行**(在有需要时记下当前的状态,转而执行响应的事件处理程序,待处理完成后再返回断点或调度其他程序) +- **实时交互的需要**(即刻响应,响应之后还能返回断点继续执行) +- **优先级支持**(对更紧急任务的支持) +- **故障报警与处理** +- **保护性操作需要,防止破坏**(在进入内核态时发生中断,发生权限变化,处理完内核态任务之后再改变权限返回,保护内核) +- **并行和进程操作/交互的需要**(时间片) + +#### 中断和异常的区别 + +从发生源角度和处理方式角度划分为了中断和异常. 但是他们处理问题的方式和思路本质是一样的. + +中断指I/O设备发出,也成为外中断.外部事件 +异常是正在执行的指令引发的,cpu执行指令本身出现问题=>响应错误/异常处理程序,执行系统调用(通过trap) + +中断解决cpu和设备间并行操作;异常解决cpu执行指令时出现的问题处理(算数溢出/地址越界...) + +外中断,也是中断,异步中断,是指来自处理器之外的中断信号,包括时钟中断、键盘中断、它机中断和外部设备中断。外中断又分==可屏蔽中断==和==不可屏蔽中断==,各个中断具有不同的优先级,表示事件的紧急程度,==在处理高一级中断时往往会部分或全部屏蔽低级中断==。因最开始的中断仅针对外中断,因此外中断也直接称作中断。 + +内中断,又称异常,同步中断,是指来自处理器内部的中断信号,通常是由于在程序执行过程中,**发现与当前指令关联的、不正常的或错误的事件**。==内中断不能被屏蔽,一旦出现必须立即予以响应并进行处理==,只是处理程序运行过程中可以选择是否屏蔽其它中断或屏蔽哪些中断。 内中断可细分为: +* 访管中断,由系统程序执行访管指令引起,可以看做机器指令的一种扩充; +* 硬件故障中断,如:电源失效、奇偶校验错误,总线超时; +* 程序性中断,如:非法操作、地址越界、页面故障、调试指令、除数为0和浮点溢出等。 + +中断由外部的中断控制器进行触发和响应. +异常由cpu内部的中断处理器电路控制. + +中断和异常的区别 +![[Pasted image 20230223094133.png]] +关于它们的区别有两点是需要注意的: +平常所说的屏蔽中断是不包括异常的,即异常不会因为CPU的IF位被清(关中断,指令:cli)而受影响,比如缺页异常,即使关了中断也会触发CPU的处理,回答了我上面红色部分疑问。 +通常说的int 80h这种系统调用使用的中断方式实际上硬件上是理解为异常处理的,因此也不会被屏蔽掉,这也很好理解,int 80h这种中断方式是程序里主动触发的,对于CPU来说属于同步事件,因此也就属于异常的范畴。 + +### 为什么中断处理过程中不能被阻塞,而异常处理过程却可以? + +这是一个从解决问题考虑的设计思路问题,中断是外部设备发出, 你没办法决定是否可以忽略,所以只能立刻响应, 至于做不做事是可以决定的. +异常所提供的服务本就是当前进程所需要的,故而当进程需要阻塞的时候,便会在异常处理程序中设置阻塞。所以它是你自己可控的你可以决定它是否可以阻塞. + +## 中断/异常分类 + +图1 + + + + + +![](https://pic1.zhimg.com/80/v2-2003613a2b6bb8be504675c79dbc8a54_720w.webp) + + +Scannable Document on Jan 6, 2021 at 9_18_46 AM.png + +按中断源进行分类:发出中断请求的设备称为中断源。按中断源的不同,中断可分为 +内中断:即程序运行错误引起的中断 +外中断:即由外部设备、接口卡引起的中断 +软件中断:由写在程序中的语句引起的中断程序的执行,称为软件中断 + +允许/禁止(开/关)中断: CPU通过指令限制某些设备发出中断请求,称为屏蔽中断。从CPU要不要接收中断即能不能限制某些中断发生的角度 ,中断可分为 +可屏蔽中断 : +可被CPU通过指令限制某些设备发出中断请求的中断, 那是不是意味着进中断时disable整个中断,其实disable的都是可屏蔽中断? +不可屏蔽中断: +不允许屏蔽的中断如电源掉电 + +可屏蔽中断, +I/O设备发出的所有中断请求(IRQ)都产生可屏蔽中断,一个屏蔽的中断只要还是屏蔽的,控制单元就可以忽略它。 +非屏蔽中断,有一些危险的事件才能引起非屏蔽中断,例如硬件故障,非屏蔽中断总是由CPU辨认。 + +## 中断/异常工作机制 + +硬件软件同时支持才能完成. +由硬件捕获响应,软件识别类型然后处理. +每个中断/异常都有个号码,由硬件设计者或者操作系统设计者定义 + +大致流程: +硬件捕获中断(某个针脚高电压)->根据内容按规矩编码(中断码)->写入中断寄存器 +cpu执行指令周期的最后时刻扫描中断寄存器->暂停当前程序->保护现场->根据中断码去中断向量表查询->找到地址及相关状态参数->执行中断程序->恢复 + +## 中断/异常的软硬件支持结构 + +os: +操作系统设计时,提前设置中断/异常处理程序和向量表 +设计和实现中断处理程序 +设计处理程序的向量表 +运行时响应中断 + +中断码: 中断硬件对中断内容按规则编码,送入程序状态字寄存器(PSW)的相应位 中断向量表: 硬件查的表 映射中断处理程序 中断向量: 它是内存单元 存储处理程序入口地址,程序运行所需的处理机状态字 + +硬件: +中断寄存器: +保存中断信号 +cpu响应: +在指令执行周期最后时刻扫描中断寄存器,看是否有 +判断是否允许中断 + +硬件的工作:(捕获/响应) +* 捕获中断源请求 +* 响应 +* 控制权交给特定处理程序 +软件的工作:(处理) +* 识别中断/异常类型 +* 完成处理(软件本身为处理程序) + +## 实施/保护模式 + +在X86中,分为实模式和保护模式,实模式通常是CPU启动到BIOS再到操作系统启动前的这段时间,操作启动初始化完成进入到保护模式。 + +## 补充知识 + +常见异常: + +- 算数溢出 +- 除零 +- 取数奇偶校验错 +- trap指令(system call) +- 硬件改变cpu执行流程 +- 地址越界 +- 页错误/故障 +- 保护性异常(写仅读内存) +- 断点指令 + +常见中断: + +- I/O中断 +- 时钟中断 +- 硬件故障 + +图2 + +中断允许触发器:在CPU内部设置一个中断允许触发器,只有该触发器置“1”,才允许中断;置“0”,不允许中断。 + +指令系统中,开中断指令,使中断触发器置“1” 关中断指令,使中断触发器置“0” + +中断优先级:为了管理众多的中断请求,需要按每个(类)中断处理的急迫程度,对中断进行分级管理,称其为中断优先级。在有多个中断请求时,总是响应与处理优先级高的设备的中断请求。 + +中断嵌套:当CPU正在处理优先级较低的一个中断,又来了优先级更高的一个中断请求,则CPU先停止低优先级的中断处理过程,去响应优先级更高的中断请求,在优先级更高的中断处理完成之后,再继续处理低优先级的中断,这种情况称为中断嵌套。 + +中断又可以分为可屏蔽中断和非可屏蔽中断, +中断屏蔽是指 禁止 CPU 响应或禁止中断产生。前者是指 CPU 暂时不响应中断,等中断开放了被屏蔽的中断才能被响应,防止同级或高级的中断影响。后者是中断的事件发生时直接不允许提出中断请求也不能通知 CPU。 + +多重中断有几种处理方法,一种是串行处理,CPU 响应中断的时候屏蔽其它部分或所有中断;第二种是即时处理,运行中断的过程中,如果出现程序性中断(异常),一般情况表明此时中断处理程序有异常,应对其进行立即响应;第三种是嵌套处理,对于有些必须处理的高优先级的中断事件,采用屏蔽的方法不妥,因此允许某些中断处理程序时依然能够响应中断。操作系统必须预先规定每类中断的优先级,中断嵌套一般不会超过 3 重,过多嵌套会增加系统不必要的开销。 + +## 系统调用 + +系统调用使用trap实现, 是用户态到内核态的唯一入口(调用操作系统接口使用特权指令) +特殊指令: +是trap/访管指令,调用不同系统接口的统一入口,根据号和参数区分 +流程: +通过trap一发异常-> 用户态切换到内核态->传参执行 + +### 用户参数如何传入内核 + +三种方式: + +1. trap指令自带参数(数量有限) +2. 通用寄存器,通用方案,寄存器个数有限 +3. 内存中专门对战区 + +### 地址空间 +地址空间的约定:一般用户和内核的地址空间在相差比较大的地方。cache攻击 +MMIO PIO +Memory Map IO and Port IO +内核嵌套中断 +page fault是异常 +异常向量表的设置:CPU上电之后立即执行,是系统初始化的主要工作之一,在开启中断和启动第一个应用之前。 +内核运行的时候可能会有嵌套中断: +1. 内核执行过程中发生了缺页(用户的地址和内核相差很多的目的就是尽量减少内核的页表被swap) +2. 内核执行过程中出现外部设备中断 +3. 内核接收到别的核的用户程序主动发的syscall +![[SYSCALL传参数.jpg]] +但是用户态可以利用构造一个非法的指针,通过syscall攻击内核,内核翻译这些虚拟地址时就会造成各种问题,于是内核就会做相应的检查,防止出现一个未映射区域或者非法访问,如果是page fault,直接帮它call swap page就行 +FixSC:flexible syscall,如果有多出来的核,可以给用户和内核各一个数据页,拿出一个核专门做在内核和用户态之间传递相关数据,避免syscall的开销; + +## 时钟中断 +时钟中断(Clock Interrupt)是一种计算机硬件中断,它是由 CPU 内部的硬件定时器产生的,用于确保操作系统和应用程序在运行过程中能够获得适当的时间片并进行调度。 + +当 CPU 启动时,定时器开始计数。当定时器的计数值达到预设的阈值时,CPU 就会产生一个时钟中断。时钟中断会暂停正在执行的进程,并将 CPU 的控制权移交给操作系统内核来处理。在内核中,时钟中断通常被用来执行以下几个任务: + +1. 时间管理:时钟中断可以帮助操作系统跟踪时间的流逝,从而保证正确地记录日志、备份数据等。 +2. 进程调度:时钟中断可以触发进程调度,使得操作系统能够按照特定的算法决定哪些进程获得 CPU 的使用权。 +3. 虚拟内存管理:时钟中断可以触发虚拟内存管理机制,从而允许操作系统重新分配页面并回收未使用的内存。 + +时钟中断的频率通常是固定的,且与 CPU 的主频有关。例如,在一个 1 GHz 的 CPU 上,时钟中断通常以每秒 1000 次的速度运行。操作系统可以根据需要调整时钟中断的频率,以实现更好的性能和功耗平衡。 + +总之,时钟中断是计算机硬件中的一种机制,它可以帮助操作系统跟踪时间的流逝、执行进程调度和虚拟内存管理等任务。 \ No newline at end of file diff --git "a/dongshen/\347\241\254\344\273\266\344\270\255\346\226\255\345\222\214\350\275\257\344\273\266\344\270\255\346\226\255 \347\241\254\344\270\255\346\226\255\345\222\214\350\275\257\344\270\255\346\226\255.md" "b/dongshen/\347\241\254\344\273\266\344\270\255\346\226\255\345\222\214\350\275\257\344\273\266\344\270\255\346\226\255 \347\241\254\344\270\255\346\226\255\345\222\214\350\275\257\344\270\255\346\226\255.md" new file mode 100644 index 0000000..0065272 --- /dev/null +++ "b/dongshen/\347\241\254\344\273\266\344\270\255\346\226\255\345\222\214\350\275\257\344\273\266\344\270\255\346\226\255 \347\241\254\344\270\255\346\226\255\345\222\214\350\275\257\344\270\255\346\226\255.md" @@ -0,0 +1,29 @@ +[[API]] +中断机制:CPU在执行指令时,收到某个中断信号转而去执行预先设定好的代码,然后再返回到原指令流中继续执行,这就是中断机制 +### software interruption +A software interrupt is a type of interrupt ==generated by software, rather than a hardware device==, in a computer system. It is used to request a service or notify the operating system kernel of an event. +When a software interrupt is generated, the CPU suspends the execution of the current program and switches to kernel mode to execute a corresponding software interrupt handler routine. +Software interrupts are often used by ==applications to communicate with the operating system or to **request services from the kernel==** +### hardware interruption +A hardware interrupt is a signal generated by a hardware device. +When a hardware interrupt occurs, the CPU stops the current task it is executing and switches to a special mode called ==interrupt mode== to handle the interrupt. The processor saves the current program state and registers, and then jumps to the appropriate ==interrupt handler routine==, which is **a small section of code** designed to handle the specific interrupt. +### softirq +Like hardware interrupts, softirqs are a type of interrupt that can **preempt the normal execution of the kernel and execute an interrupt handler routine** and has its own context. However, unlike hardware interrupts, softirqs are **generated by software**, not hardware devices. +A softirq is a mechanism used by the Linux kernel to handle deferred processing tasks that **require a high priority but cannot be handled directly in hardware interrupts**. +==used by the kernel to handle **high-priority** tasks that cannot be handled directly in hardware interrupts due to their complexity or overhead.== +Softirq handlers are executed in a **preemptive manner,** which means that they can be interrupted by higher-priority softirqs or hardware interrupts. This allows the kernel to handle high-priority tasks in a timely and efficient manner while maintaining system responsiveness and throughput. +硬件中断和硬中断一样 +#### 中断的来源(区分软件/硬件中断) +1.外设,外设产生的中断信号是异步的,一般也叫做**硬件中断(** 注意硬中断是另外一个概念)。硬件中断按照是否可以屏蔽分为可屏蔽中断和不可屏蔽中断。例如,网卡、磁盘、定时器都可以产生硬件中断。 + +2.CPU,这里指的是一个CPU向另一个CPU发送中断,这种中断叫做IPI(处理器间中断)。IPI也可以看出是一种特殊的**硬件中断**,因为它和硬件中断的模式差不多,都是异步的。 + +3.CPU异常,CPU在执行指令的过程中发现异常会向自己发送中断信号,这种中断是同步的,一般也叫做**软件中断(由软件比如应用程序和操作系统来发起)** (注意软中断是另外一个概念)。CPU异常按照是否需要修复以及是否能修复分为3类:1.==陷阱(==trap),不需要修复,中断处理完成后继续执行下一条指令,2.==故障==(fault),需要修复也有可能修复,中断处理完成后重新执行之前的指令,3.==中止==(abort),需要修复但是无法修复,中断处理完成后,进程或者内核将会崩溃。例如,缺页异常是一种故障,所以也叫缺页故障,缺页异常处理完成后会重新执行刚才的指令。 +4.中断指令,直接用CPU指令来产生中断信号,这种中断和CPU异常一样是同步的,也可以叫做软件中断。例如,中断指令int 0x80可以用来实现系统调用。 + +#### 中断的作用 +设计中断机制的目的在于中断机制有以下4个作用,这些作用可以帮助操作系统实现自己的功能。这四个作用分别是: +**1.外设异步通知CPU:** 外设发生了什么事情或者完成了什么任务或者有什么消息要告诉CPU,都可以异步给CPU发通知。例如,网卡收到了网络包,磁盘完成了IO任务,定时器的间隔时间到了,都可以给CPU发中断信号。 +**2.CPU之间发送消息:** 在SMP系统中,一个CPU想要给另一个CPU发送消息,可以给其发送IPI(处理器间中断)。 +**3.处理CPU异常:** CPU在执行指令的过程中遇到了异常会给自己发送中断信号来处理异常。例如,做整数除法运算的时候发现被除数是0,访问虚拟内存的时候发现虚拟内存没有映射到物理内存上。 +**4.实现系统调用:** 早期的系统调用就是靠中断指令来实现的,后期虽然开发了专用的系统调用指令,但是其基本原理还是相似的。 \ No newline at end of file diff --git "a/dongshen/\347\272\277\347\250\213 \350\277\233\347\250\213.md" "b/dongshen/\347\272\277\347\250\213 \350\277\233\347\250\213.md" new file mode 100644 index 0000000..288364e --- /dev/null +++ "b/dongshen/\347\272\277\347\250\213 \350\277\233\347\250\213.md" @@ -0,0 +1,169 @@ +[[操作系统期末考试]] +线程、进程和协程都是计算机程序中常用的并发编程模型,它们之间有以下几个区别: +1. 资源分配:进程是操作系统资源分配的基本单位,包括代码、数据、堆栈等,**每个进程都有独立的内存空间和系统资源**。而线程是进程的一个执行单元,**同一进程中的线程共享相同的内存空间和系统资源,并且可以独立运行,但线程之间的切换开销比进程小。** +2. 执行方式:进程和线程都是**抢占式调度**的,由操作系统负责调度,其执行方式是由操作系统控制的。而协程是**协作式调度**的,由程序员手动控制切换(Yield),其执行方式可以更加高效和灵活。 +3. 上下文切换:进程之间切换会涉及到大量的上下文切换、内存映射等操作,开销较大;线程之间切换开销相对较小;而协程的切换只需要保存少量上下文信息,开销最小。 +4. 编程复杂度:进程和线程在编程时需要考虑同步、互斥、死锁等问题,编程复杂度较高;而协程相对于进程和线程来说,编程复杂度较低,但需要手动管理协程状态,编写的程序需要遵循协作式的调度逻辑。 +5. 应用场景:进程通常用于分布式系统、操作系统等底层应用;线程一般用于网络服务、GUI编程等中层应用;协程通常用于高并发的服务器、游戏开发等上层应用。 +总之,进程、线程和协程都是计算机程序中常用的并发编程模型,它们各有特点,在不同的应用场景下可以选择合适的模型来实现高效并发编程。 +## System Call +Linux基础系统调用(syscall)是用户空间程序与内核之间的接口,通过系统调用可以让用户空间程序请求内核提供的服务,如文件操作、进程管理、网络通信等。在Linux中,系统调用通常使用软中断(software interrupt)方式实现。下面是Linux基础syscall的执行过程: + +1. 用户空间程序通过指令int 0x80或sysenter**将控制权交给内核**; +2. CPU检测到中断并转入内核模式,保存用户态寄存器的值,并切换到内核态栈; +3. 内核根据传入的系统调用号,在系统调用表中查找相应的系统调用函数,并保存系统调用参数; +4. 系统调用函数根据参数进行处理,并返回系统调用结果; +5. 内核从系统调用返回,并将返回值存放在寄存器中; +6. CPU切换回用户态,将返回值传递给用户空间程序。 +当使用sysenter指令进行系统调用时,可以绕过中断向量表的查找和处理过程,从而提高系统调用的执行效率。这里的关键在于,**在Linux内核启动时,会初始化中断向量表,并将所有的系统调用对应的中断号和中断处理函数的入口地址进行映射**。因此,当使用sysenter指令进行系统调用时,内核可以直接从该映射表中获取对应的中断处理函数的入口地址,从而实现快速执行。 +需要注意的是,系统调用是一种特殊的函数调用,涉及到用户态和内核态之间的切换,因此系统调用会带来额外的开销。为了减少这种开销,Linux提供了一些优化技术,如vDSO(virtual dynamic shared object)和seccomp(secure computing)机制等,使得系统调用的执行更加高效、安全和可靠。 + +### fork +**fork** is an operation whereby a process **creates a copy of itself.** +It is usually implemented as a C standard library wrapper to the fork, clone, or other system calls of the kernel. +For a process to start the execution of a different program, it first forks to create a copy of itself, creating a child process. **Then the child calls `exec` system call to overlay itself**: it ceases execution of its former program in favor of the other. +The fork operation creates **a separate address space** for the child. The child process **has an exact copy of all the memory segments of the parent process**. +copy-on-write semantics are implemented and the physical memory need **not be actually copied**. Instead, virtual memory pages in both processes may refer to the same pages of physical memory **until one of them writes to such a page: then it is copied**. This optimization is important in the common case where the child process performs only a small set of actions before it ceases execution of its program in favour of the program to be started, and it requires very few, if any, of its parent's data structures. +hey can then inspect the call's **return value to determine their status, child or parent**, and act accordingly. child returns 0, parent returns the mark of child processes. +子进程从父进程的文件描述符副本开始。对于进程间通信,父进程通常会创建一个或多个管道,在fork进程之后,进程关闭它们不需要的管道端。 +在发出一个**vfork**系统调用时,父进程被暂停,直至子进程完成执行或被新的可执行映像取代(通过系统调用之“exec”家族中的一项)。子进程借用父进程的MMU设置和内存页面,在父进程与子进程之间共享,不进行复制,如果子进程在任何共享页面中进行修改,不会创建新的页面,并且修改的页面对父进程同样可见。父进程会等待子进程执行,直到子进程调用`exec`创建自己的独立地址空间或者执行完退出为止。因为没有页面复制(消耗额外的内存),此技术在纯复制环境中使用exec时较普通fork更优化。 +### exec +In computing, `exec` is a functionality of an operating system that **runs an executable file in the context of an already existing process, replacing the previous executable**. This act is also referred to as an **overlay**. It is especially important in Unix-like systems, although it exists elsewhere. As no new process is created, the process identifier **(PID) does not change**, but the machine code, data, heap, and stack of the process are replaced by those of the new program. + +A file descriptor open remains open when an exec call is made in the new process image, unless was `fcntl`ed with `FD_CLOEXEC` or opened with `O_CLOEXEC` (the latter was introduced in POSIX.1-2001). This aspect is used to specify the standard streams (stdin, stdout and stderr) of the new program. +A successful overlay **destroys the previous memory address space of the process,** and all its memory areas, that were not shared, are reclaimed by the operating system. Consequently, all its data that were not passed to the new program, or otherwise saved, become lost. +A successful exec replaces the current process image, so it cannot return anything to the program that made the call. Processes do have an exit status, but that value is collected by the parent process. +If an exec function does return to the calling program, an error occurs, the return value is −1, +### wait +In computer operating systems, a process (or task) may wait for another process to complete its execution. In most systems, a parent process can create an independently executing child process. The parent process may then issue a `wait` system call, which suspends the execution of the parent process while the child executes. **When the child process terminates, it returns an exit status to the operating system, which is then returned to the waiting parent process.** The parent process then resumes execution. +An operating system may provide variations of the wait call that allow a process to wait for any of its child processes to exit, or to wait for a single specific child process (identified by its process ID) to exit. +**Some operating systems issue a signal (`SIGCHLD`) to the parent process when a child process terminates,** notifying the parent process and allowing it to get the child process's exit status. +The exit status returned by a child process typically indicates whether the process terminated normally or abnormally. For normal termination, this status also includes the exit code (usually an integer value) that the process returned to the system. +When a child process terminates, it becomes a **zombie** process, and continues to exist as an entry in the system process table even though it is no longer an actively executing program. Under normal operation it will typically be immediately waited on by its parent, and then reaped by the system, **reclaiming the resource** (the process table entry). If a child is not waited on by its parent, it continues to **consume this resource indefinitely, and thus is a resource leak.** Such situations are typically handled with a special **"reaper" process** that locates zombies and retrieves their exit status, allowing the operating system to then deallocate their resources. +Conversely, a child process whose parent process terminates before it does becomes an orphan process. Such situations are typically handled with a special "root" (or "init") process, **which is assigned as the new parent of a process when its parent process exits**. This special process detects when an orphan process terminates and then retrieves its exit status, allowing the system to deallocate the terminated child process. +### exit +On many computer operating systems, a computer process terminates its execution by making an exit system call. More generally, an exit in a multithreading environment means that a thread of execution has stopped running. For resource management, the operating system **reclaims resources** (memory, files, etc.) that were used by the process. The process is said to be a dead process after it terminates. +Under Unix and Unix-like operating systems, a process is started when its parent process executes a **fork** system call. The parent process may then **wait** for the child process to terminate, or may continue execution (**possibly forking off other child processes**). When the child process terminates ("dies"), either normally by calling exit, or abnormally due to a fatal exception or signal (e.g., SIGTERM, SIGINT, SIGKILL), an exit status is returned to the operating system and a SIGCHLD signal is sent to the parent process. The exit status can then be retrieved by the parent process via the **wait** system call. As the final step of termination, a primitive system exit call is invoked, **informing the operating system that the process has terminated and allows it to reclaim the resources used by the process.** That is the subroutine of cleanup +### kill(信号) +-9是信号 +kill is a command, not a sys call. +But kill is something of a *misnomer(误称)*; **the signal sent may have nothing to do with process killing**. The kill command is a wrapper around the `kill()` system call, which sends signals to processes or process groups on the system, referenced by their numeric process IDs (PIDs) or process group IDs (PGIDs). +There are many different signals that can be sent.  The default signal sent is `SIGTERM`. +>**SIGINT** "Signal interrupt" The SIGINT signal is sent to a process by its controlling terminal when a user wishes to **interrupt** the process. This is typically initiated by pressing Ctrl+C +>**SIGKILL** "Signal kill" The SIGKILL signal is sent to a process to cause it to **terminate immediately (kill)**. In contrast to SIGTERM and SIGINT, this signal **cannot be caught or ignored, and the receiving process cannot perform any clean-up upon receiving this signal**. +>**SIGTERM** "Signal terminate" The SIGTERM signal is sent to a process to request its **termination**. Unlike the SIGKILL signal, it **can be caught and interpreted or ignored by the process.** This allows the process to perform nice termination **releasing resources and saving state if appropriate**. SIGINT is nearly identical to SIGTERM. + +## Handler +系统调用syscall()可以用来**注册或修改信号处理程序**。它的函数原型为: + +```c +#include +#include + +long syscall(long number, ...); +``` + +其中,第一个参数number指定了要执行的系统调用号,后面的...表示该调用需要传入的参数列表。 +在使用syscall()注册或修改信号处理程序时,需要使用sigaction()函数设置信号的处理方式、信号的被阻塞和解除阻塞时的行为等;signal()函数则设置信号的处理方式,但比较简单,只有两种处理方式:忽略信号或者执行默认的信号处理函数。 +在信号处理程序被注册后,当系统产生一个信号时,内核就会向相应的进程发送这个信号,并将信号处理程序与该信号关联起来。当进程接收到信号时,会执行与信号关联的信号处理程序。 +```C +#include +#include + +void sigterm_handler(int signum) { + printf("Received SIGTERM signal, terminating...\n"); + // ...执行一些清理工作... + exit(0); +} + +#include +#include +#include +#include + +int main() { + struct sigaction sa; + sa.sa_handler = sigterm_handler; // 设置信号处理函数 + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + + if (sigaction(SIGTERM, &sa, NULL) == -1) { + perror("sigaction error"); + exit(1); + } + + // ...执行一些其他操作... + // 调用syscall()执行需要修改的系统调用 + syscall(SIGTERM, args); + + return 0; +} + +#include +#include +#include +#include + +int main() { + signal(SIGTERM, sigterm_handler); // 设置信号处理函数 + + // ...执行一些其他操作... + // 调用syscall()执行需要修改的系统调用 + syscall(SIGTERM, args); + + return 0; +} + +``` +### vsyscall +一些不太敏感的系统调用放到用户态来做,确保安全的情况下更加性能。 + +## syscall ABI +在Linux系统中,当应用程序调用syscall时,其返回值通常存储在EAX寄存器中,即%eax。 +在x86架构的Linux系统中,syscall使用的是系统调用号(system call number)标识需要执行的系统调用。系统调用号和参数都会被存储在寄存器中,例如使用EAX寄存器来存储系统调用号,EBX、ECX、EDX、ESI等寄存器来存储系统调用的参数。 +对于x86_64架构的系统,则使用RAX寄存器来存储系统调用号,而将其他系统调用参数放置在RDI、RSI、RDX、R10、R8以及R9等寄存器中。系统调用结束后,操作系统会将返回值保存在RAX寄存器中,应用程序可以通过读取RAX寄存器的值来获得系统调用的返回值。 + +因此,针对不同的系统架构,我们可以根据对应的ABI(Application Binary Interface,应用二进制接口)规范来获取syscall的返回值。在每种架构的系统中,ABI都会规定如何使用寄存器来传递参数、如何进行函数调用和返回值处理等细节,从而确保不同的应用程序能够在相同的系统环境中运行并交互。 + +##### 如果并行线程过多,可能会出现以下性能问题: +1. **上下文切换开销增加**:当线程数量增加时,操作系统需要频繁地进行线程之间的上下文切换,将CPU资源分配给不同的线程。但是,上下文切换本身也会产生一定的开销,因此过多的线程会导致系统的运行效率降低。 +2. **内存和缓存争用**:每个线程都需要占用一定的内存空间和CPU缓存,如果线程数目过多,可能会导致内存和缓存的争用情况加剧,从而导致性能下降。 +3. **线程阻塞和竞争条件**:线程之间可能存在相互依赖和共享资源的情况,如果线程数目过多,就容易出现线程之间的**阻塞**和**竞争条件**,从而影响程序的稳定性和可靠性。 +4. **调度延迟和饥饿现象**:在多核处理器中,线程之间可以并行执行,但是调度过程也需要时间,如果线程数目过多,就容易出现调度延迟和**饥饿**(一次拿到所有需要的资源) 现象,导致某些线程无法得到充分的CPU资源。 + +为了避免上述问题,应该尽可能控制并行线程的数量,并根据实际情况进行优化调整。例如,可以使用线程池技术来控制线程的数量和生命周期,减少不必要的上下文切换和内存开销;还可以使用锁和同步机制来避免竞争条件和阻塞现象。总之,合理地控制并行线程的数量和调度,才能保证多线程应用程序的高效、稳定和可靠性。 + +##### 换页的开销 +在操作系统中,为了将物理内存资源充分利用,会使用虚拟内存技术来实现透明的内存管理。虚拟内存技术允许进程使用比其物理内存容量更大的虚拟地址空间,**当进程需要访问不在物理内存中的页面时,就会产生缺页中断(Page Fault),再从磁盘中读取所需页面到物理内存中,这个过程称为“换页”(Swap)。** + +在进行换页时,由于需要访问外部设备磁盘,因此会产生较大的开销,主要包括以下几个方面: +1. **I/O延迟**:读取磁盘数据是一个相对较慢的操作,通常涉及到磁盘寻道、旋转等机械操作,尤其是当磁盘请求队列较长或者磁盘故障时,I/O延迟会显著增加。 +2. **内存带宽开销**:当系统在进行页面置换时,需要将被置换出的页面写入到磁盘中,同时读取要置换的页面到内存中。这一过程需要**占用内存带宽,可能会影响其他正在运行的进程的性能**。 +3. CPU时间片浪费:当进程发生缺页中断时,操作系统需要暂停当前进程的执行,进行页面置换和I/O操作,直到磁盘数据读取完毕并完成页面替换后才能继续运行。当进程需要等待I/O操作、发生缺页中断、或者由于其他原因导致暂停执行时,**操作系统会将CPU资源分配给其他处于就绪状态的进程,直到当前进程再次准备好执行为止**。这种切换过程称为上下文切换(Context Switch),包括保存当前进程的状态和加载另一进程的状态,上下文切换也会有比较多的时间占用。 +4. 预取机制的不合理有可能会进一步拖累系统性能。空间本地性或者事件本地性不强的时候。 +因此,为了减少换页带来的开销,可以采取以下措施: +1. 增加物理内存:如果系统物理内存容量充足,就可以减少内存页面置换的频率,从而降低I/O延迟和内存带宽开销。 +2. 优化页面置换算法:选择合适的页面置换算法,如最近最少使用(LRU)算法、先进先出(FIFO)算法等,可以提高页面置换的效率,减少开销。 +3. 提高磁盘性能:通过提高磁盘读写速度、增加磁盘缓存、调整磁盘调度策略等方法,可以降低磁盘I/O延迟,提高页面读写效率。 +4. 减少进程数目和应用程序的内存占用:避免同时运行过多的进程和应用程序,可以减少页面置换的发生次数,降低CPU时间片的浪费。 + +总之,由于换页是一项关键的系统操作,它的开销会显著影响系统整体性能。因此,需要针对具体的应用场景和系统负载情况,选择合适的优化策略,以提高系统的性能和稳定性。 + +### LSCPU +超线程个数=逻辑CPU的个数 +![[Pasted image 20230531203129.png]] +**real 整个程序从开始到结束的时间。 +user 在用户态跑这个程序所用的时间,不包括被阻塞,在cpu上计算的时间。 +sys 处在内核态的时间。 +如果充分利用多核跑,real小于user +如果单核跑,real一般约等于user+sys,大于也可能 +如果是IO密集型/缺页很多,real远大于user** +sleep就是进入内核态把这个程序标记为被阻塞,到时间再来唤醒。中间cpuidle或者执行别的进程。sleep的时间不在user也不在sys(在内核标记、唤醒的时间非常短。) +## Turbo Boost of Intel +CPUs don’t always need to run at their maximum frequency. Some programs are more dependent on memory to run smoothly, while others are CPU-intensive. Intel® Turbo Boost Technology is an energy-efficient solution to this imbalance: **it lets the CPU run at its base clock speed when handling light workloads, then jump to a higher clock speed for heavy workloads.** +Running at a lower clock rate (the number of cycles executed by the processor every second) allows the processor to use less power, which can **reduce heat and positively impact battery life in laptops**. But when more speed is needed, Intel® Turbo Boost Technology dynamically increases the clock rate to compensate. This is sometimes called “algorithmic overclocking”. + +提高CPU频率可以提高运行速率的原因主要是增加了CPU的时钟周期,从而使得CPU在单位时间内可以处理更多的指令和数据。 +当 CPU 的时钟频率提高时,每个时钟周期的长度就会变短,CPU 可以在同样的时间内完成更多的指令执行。例如,如果一个 CPU 的时钟频率为 2GHz(即每秒钟有 20亿个时钟周期),那么每个时钟周期的长度约为 0.5 纳秒。如果将时钟频率提高到 4GHz,那么每个时钟周期的长度就缩短到了 0.25 纳秒,CPU 在同样的时间内可以执行更多的指令,从而提高运行速率。 +此外,提高 CPU 频率还可以使得 CPU 更快地读取和写入内存、缓存等数据结构,从而加快程序的执行速率。 +不过,需要注意的是,频率并不是唯一决定 CPU 性能的指标,还有很多其他因素如微架构设计、指令集支持等对 CPU 的性能有重要影响。同时,提高 CPU 频率也会带来一定的热量问题和功耗消耗问题,需要适当调节 CPU 的供电和散热系统以保证稳定性。 \ No newline at end of file diff --git "a/dongshen/\350\231\232\346\213\237\345\214\226\344\270\216\345\256\211\345\205\250.md" "b/dongshen/\350\231\232\346\213\237\345\214\226\344\270\216\345\256\211\345\205\250.md" new file mode 100644 index 0000000..af9d802 --- /dev/null +++ "b/dongshen/\350\231\232\346\213\237\345\214\226\344\270\216\345\256\211\345\205\250.md" @@ -0,0 +1,22 @@ +VM exit 是指虚拟机执行过程中需要从虚拟化环境下陷到 hypervisor 的过程。这种情况通常发生在虚拟机试图访问某些受保护的资源或执行一些特殊的指令时,例如: +1. **I/O 操作**:当虚拟机试图对设备进行读写操作时,会触发 VM exit,然后 hypervisor 接管操作并转换为对物理设备的访问。 +2. **内存映射操作**:当虚拟机试图访问被 hypervisor 保护的内存区域时,会触发 VM exit,然后 hypervisor 将该内存区域映射到虚拟机的地址空间中。 +3. **特权指令**:当虚拟机执行一些特权指令(如修改页表、设置中断向量表等)时,由于它们可能会影响整个系统的运行和稳定性,因此会触发 VM exit,然后 hypervisor 接管操作并进行处理。 +4. **中断/异常处理**:当虚拟机收到硬件中断或异常信号时,会触发 VM exit,然后 hypervisor 接管中断和异常处理,并将结果返回给虚拟机。 +总之,VM exit 是由于虚拟机试图访问受保护的资源或执行一些特殊的指令而触发的,这时虚拟机需要从虚拟化环境下陷到 hypervisor 中进行处理。对于 VM exit 的处理方式和效率会对虚拟机的性能和响应时间产生影响,因此需要通过优化虚拟化环境、调整虚拟机设置等措施来减少 VM exit 的次数和开销。 +为了减少从虚拟机下陷到 hypervisor 的次数,可以采取以下措施: +1. 适当调整虚拟机设置:可以通过调整虚拟机的 CPU 分配、内存大小、网络带宽等参数来优化虚拟机的性能,从而减少从虚拟机下陷到 hypervisor 的频率。 + >1. 减少需要 VM exit 的操作:当虚拟机的 CPU、内存或网络性能较低时,它**可能会频繁地进行 I/O 操作、内存访问等操作**(带宽不够),这些操作可能需要从虚拟化环境下陷到 hypervisor,并触发 VM exit。如果虚拟机的性能得到提升,它就可以更快地完成这些操作,从而减少了需要 VM exit 的次数。例如,**如果虚拟机的 CPU 性能不足,它就可能会频繁进行上下文切换**,并且无法充分利用 CPU 的时间片,这样会导致 VM exit 的次数增多。如果调整虚拟机的 CPU 分配,使其得到更多的 CPU 时间片,就可以减少上下文切换和 VM exit 的次数。 + >2. 加速 VM exit 的处理:当 VM exit 确实需要发生时,如果 hypervisor 可以更快地处理它,就可以减少 VM exit 的耗时,从而提高整个系统的性能和响应时间。例如,对于一些常见的 VM exit 原因,如 I/O 操作、内存映射等,可以采用硬件加速技术(如 Intel VT-x、AMD-V)来加快 hypervisor 对 VM exit 的处理速度。此外,还可以通过优化虚拟化软件的实现方式、采用更好的调度策略等方式来加快 VM exit 的处理速度。 +2. 使用硬件辅助技术:现代 CPU 支持一些硬件辅助技术,如 Intel VT-x、AMD-V 等,这些技术可以支持虚拟机的直接执行和共享资源,从而减少从虚拟机下陷到 hypervisor 的操作次数。**硬件虚拟化(EL2),设备直通。** +3. 避免不必要的 VM exit:可以通过避免不必要的指令或操作,如 I/O 操作、内存访问、中断处理等,来减少从虚拟机下陷到 hypervisor 的次数。**内存虚拟化、中断虚拟化、I/O虚拟化。** +4. 优化虚拟化软件:虚拟化软件本身也可以进行优化,如针对常见的 VM exit 原因进行优化、采用更好的调度策略、使用更高效的中断处理方式等等,从而减少从虚拟机下陷到 hypervisor 的次数。 +总之,为了减少从虚拟机下陷到 hypervisor 的次数,可以通过适当调整虚拟机设置、使用硬件辅助技术、避免不必要的 VM exit 和优化虚拟化软件等多种方式来实现。这样可以提高系统的性能和响应时间,从而更好地支持虚拟化环境。 +### Watchdog +watchdog(看门狗)是一种系统监控机制,它可以检测和处理系统中的故障或错误状态。具体来说,watchdog 会周期性地向系统发送一个“心跳信号”,以确保系统正常运行,如果系统出现故障或意外停止运行,watchdog 就会触发相应的处理流程,如自动重启系统等。 +在嵌入式系统、服务器等关键领域中,watchdog 是一种重要的安全机制。通过定期检测系统状态和自动处理异常情况,watchdog 可以提高系统的可用性和稳定性,避免因系统故障而导致数据损失和业务中断等问题。 +watchdog 的实现方式有多种,其中最常见的是基于硬件的 watchdog,即使用专门的硬件电路或芯片来实现 watchdog 机制。这种硬件 watchdog 能够独立于系统 CPU 运行,并且可以在系统故障时自动触发特定的操作,如重启系统或触发警报等。 +除了硬件 watchdog,还有基于软件的 watchdog 实现方式。软件 watchdog 通常是通过在系统内核中增加相应模块或驱动程序来实现的,它可以定期检测系统状态,并根据需要触发相应的操作。与硬件 watchdog 相比,软件 watchdog 的实现成本更低,但需要消耗系统资源并对系统性能产生影响。 +总之,watchdog 是一种系统监控机制,通过定期检测系统状态和自动处理异常情况来提高系统的可用性和稳定性。它包括基于硬件的 watchdog 和基于软件的 watchdog 两种实现方式,并在关键领域中得到广泛应用。 +在多核场景中,watchdog 仍然是一种重要的系统监控机制。由于现代计算机通常都配备有多个 CPU 核心,因此需要使用 watchdog 机制来监测和处理多个核心之间的故障或错误状态。 +在多核场景中,可以使用多个 watchdog 来分别监测不同的 CPU 核心,以避免单一 watchdog 过度集中处理工作而导致性能下降或不稳定的情况。此外,还可以通过优化 watchdog 的实现方式、调整 watchdog 的周期等方式来提高系统的响应速度和准确性。 \ No newline at end of file diff --git "a/dongshen/\350\277\233\347\250\213\351\227\264\351\200\232\344\277\241.md" "b/dongshen/\350\277\233\347\250\213\351\227\264\351\200\232\344\277\241.md" new file mode 100644 index 0000000..d7560bd --- /dev/null +++ "b/dongshen/\350\277\233\347\250\213\351\227\264\351\200\232\344\277\241.md" @@ -0,0 +1,16 @@ +#### inter-process communication (IPC) +1. Pipes: between two processes running on the same machine. One process writes data to the pipe, and the other process reads from it. +2. Shared Memory: Shared memory is a technique that allows two or more processes to access the same area of memory. faster. +3. Message Queues: One process sends a message to a queue, and another process reads from the same queue to receive the message. +4. Sockets: communication by a network. One process establishes a socket, and the other process connects to it. +5. [[Semaphores]]: A semaphore is a synchronization tool that allows processes to synchronize access to a shared resource. It is often used in combination with shared memory to ensure that multiple processes can access the same memory area without conflicts. +#### reduce the conflicts in IPC ( or deal with Race Condition) +1. Mutual Exclusion: implemented using synchronization primitives such as **semaphores, mutexes, or locks**. When a process wants to access a shared resource, it first requests **the mutual exclusion lock**. If the lock is available, the process can proceed to access the resource. When it is done, it releases the lock so that another process can acquire it. If the lock is not available, the process waits until it becomes available. preventing conflicts in shared memory, critical sections, or other shared resources. + 保证临界区的操作都是原子操作 atomic operation +2. Synchronization: using synchronization primitives such as **signals, events, or barriers**. For example, memory barrier/ message queue `mb()` +3. Message Passing: using message queues, pipes, or sockets. When a process wants to send data to another process, it puts the data into a message or packet and sends it to the receiving process, preventing conflicts in situations where processes need to exchange data but should not access each other's memory directly. +4. Priority Scheduling: using scheduling algorithms that assign priorities to processes based on their importance or urgency. For example, a process that is handling critical data might be given a higher priority than a process that is handling non-critical data. +5. Resource Allocation: algorithms that allocate resources based on some criteria, such as the amount of resources required or the time required to complete a task. + + [[Mutual Exlusion]] + [[SD RSDL in Linux]] From b6835b640a1b63b493fa1fdce56ba1e9cbc2168c Mon Sep 17 00:00:00 2001 From: shen-dong Date: Sat, 17 Jun 2023 02:26:30 +0800 Subject: [PATCH 2/2] W6D2 & W10D2 & W14D2: dongshen --- .../VM.md | 0 W14D2/Review.md | 58 +++++ W6D2/FS.md | 27 +++ dongshen/deadlock.md | 22 -- ...55\345\222\214\345\274\202\345\270\270.md" | 204 ------------------ ...14\350\275\257\344\270\255\346\226\255.md" | 29 --- ...7\347\250\213 \350\277\233\347\250\213.md" | 169 --------------- ...13\351\227\264\351\200\232\344\277\241.md" | 16 -- 8 files changed, 85 insertions(+), 440 deletions(-) rename "dongshen/\350\231\232\346\213\237\345\214\226\344\270\216\345\256\211\345\205\250.md" => W10D2/VM.md (100%) create mode 100644 W14D2/Review.md create mode 100644 W6D2/FS.md delete mode 100644 dongshen/deadlock.md delete mode 100644 "dongshen/\344\270\255\346\226\255\345\222\214\345\274\202\345\270\270.md" delete mode 100644 "dongshen/\347\241\254\344\273\266\344\270\255\346\226\255\345\222\214\350\275\257\344\273\266\344\270\255\346\226\255 \347\241\254\344\270\255\346\226\255\345\222\214\350\275\257\344\270\255\346\226\255.md" delete mode 100644 "dongshen/\347\272\277\347\250\213 \350\277\233\347\250\213.md" delete mode 100644 "dongshen/\350\277\233\347\250\213\351\227\264\351\200\232\344\277\241.md" diff --git "a/dongshen/\350\231\232\346\213\237\345\214\226\344\270\216\345\256\211\345\205\250.md" b/W10D2/VM.md similarity index 100% rename from "dongshen/\350\231\232\346\213\237\345\214\226\344\270\216\345\256\211\345\205\250.md" rename to W10D2/VM.md diff --git a/W14D2/Review.md b/W14D2/Review.md new file mode 100644 index 0000000..759ecc4 --- /dev/null +++ b/W14D2/Review.md @@ -0,0 +1,58 @@ +## 线程 进程 +8-core CPU: when pthread +real/yield time +turbo: change the CPU frequency, thus change the speed +## 优先级反转 +优先级反转 +优先级继承:如果在pthread转换的时候发现了锁,为了避免轮空,让$T_2$继承$T_1$的优先级 + lock unlock +$T_1$—————————— ——————————— +$T_2$ ——— + lock +transaction抽象 +## 内存 +vdso等内存段 +内存应不应该能感觉到地址页的存在 +buddy伙伴算法应该出现在哪里进行管理,地址异或,位图bit +MMU `MAKE_SATP` +KPTI: page table $\rightarrow$ kernel page table isolation +from user state to kernel state, we have to flush all the TLB + +软链接和硬链接中inode的区别是什么 +superblock backup stored on blocks: ? +mmap读写与普通文件系统的区别,`char *`读写不会把整个文件全部load进来 +类FAT文件系统的缺点是什么,如何实现变长度读?引入page +## 虚拟化与安全 +虚拟机内翻译一次虚拟地址多少次内存访问 +watchdog +rcu: detect stalls +NMI +cli关中断 +kernel thread (not process): share memory space +内核挂了:狗死了 +VMX root mode/VMX non-root mode +Guest OS/Guest User/Guest Kernel +CR3 points to the PA of virtual machine +GVA $\rightarrow$ GPA $\rightarrow$ HPA +software realizing? 四级 20/16 times of read +hardware realizing? no virtualization, I/O interruption via kvm to host machine +## Fork分析 +## 综合设计 +### VMEXIT +GPU I/O interruption $\rightarrow$ via kvm in Host OS $\rightarrow$ VCPU/VGPU $\rightarrow$ come back to host to handle interrupt +The process of devisualization and coming back to host is consuming a lot of time +Non-Latency and in great number +Zheng Wenxin: Delay+Batch +I/O thread: collect all the interruptions in one queue and when it accumulates to some extent, just trigger one kvm processing, we hope to avoid strenuous exit from virtual machine. +In which condition will this be better? +### NUMA +when the number of cores are increased to an extent, then the cache collision will be very serious, so the throughput will decrease greatly. +A list of locks, and when one pthread gets the lock and change the variable, the next lock in the list will wait for it. +So at a time, there are only two pthreads fighting for that variable. +This will decrease the cache covariance and ensure justice. +avoid the core which is farther to the data failing all the time. +### 可信执行环境 +TEE: protect from Host OS. +If the computing is performed only in CPU or GPU, we can isolate the computing in hardware. +But if there are interaction between CPU and GPU +crypto + CPU can be in TEE. \ No newline at end of file diff --git a/W6D2/FS.md b/W6D2/FS.md new file mode 100644 index 0000000..7a3f4f0 --- /dev/null +++ b/W6D2/FS.md @@ -0,0 +1,27 @@ +File System +文件系统是系统对文件的存放排列方式,不同格式的文件系统关系到数据是如何在磁盘进行存储,文件名、文件权限和其他属性也存在不同。Windows操作系统支持 NTFS, FAT32, and exFAT三种不同文件系统。NTFS是目前Windows系统中一种现代文件系统,目前使用最广泛,内置的硬盘大多数都是NTFS格式。FAT32是一种相对老旧的文件系统,不能像NTFS格式支持很多现代文件格式的属性,但对于不同系统平台具有良好的兼容性,可以在Linux、Mac或Android系统平台上通用。exFAT是FAT32文件格式的替代品,很多设备和操作系统都支持该文件系统,但是目前用的不多。 +1、Fat32 +2、exFAT +3、NTFS + +### 软链接和硬链接 +有时候我们希望给某个文件取个别名,那么在 Linux 中可以通过硬链接(Hard Link) 和软链接(Symbolic Link) 的方式来实现,它们都是比较特殊的文件,但是实现方式也是不相同的。 + +硬链接是多个目录项中的「索引节点」指向一个文件,也就是指向同一个 inode,但是 inode 是不可能跨越文件系统的,每个文件系统都有各自的 inode 数据结构和列表,所以硬链接是不可用于跨文件系统的。由于多个目录项都是指向一个 inode,那么只有删除文件的所有硬链接以及源文件时,系统才会彻底删除该文件。 + +软链接相当于重新创建一个文件,这个文件有独立的 inode,但是这个文件的内容是另外一个文件的路径,所以访问软链接的时候,实际上相当于访问到了另外一个文件,所以软链接是可以跨文件系统的,甚至目标文件被删除了,链接文件还是在的,只不过指向的文件找不到了而已。 + +### 文件 I/O +文件的读写方式各有千秋,对于文件的 I/O 分类也非常多,常见的有 + +缓冲与非缓冲 I/O +直接与非直接 I/O +阻塞与非阻塞 I/O VS 同步与异步 I/O +接下来,分别对这些分类讨论讨论。 + +缓冲与非缓冲 I/O +文件操作的标准库是可以实现数据的缓存,那么根据「是否利用标准库缓冲」,可以把文件 I/O 分为缓冲 I/O 和非缓冲 I/O: - 缓冲 I/O,利用的是标准库的缓存实现文件的加速访问,而标准库再通过系统调用访问文件。 - 非缓冲 I/O,直接通过系统调用访问文件,不经过标准库缓存。 + +这里所说的「缓冲」特指标准库内部实现的缓冲。 + +比方说,很多程序遇到换行时才真正输出,而换行前的内容,其实就是被标准库暂时缓存了起来,这样做的目的是,减少系统调用的次数,毕竟系统调用是有 CPU 上下文切换的开销的。 \ No newline at end of file diff --git a/dongshen/deadlock.md b/dongshen/deadlock.md deleted file mode 100644 index 0392f13..0000000 --- a/dongshen/deadlock.md +++ /dev/null @@ -1,22 +0,0 @@ -**deadlock** is any situation in which no member of some group of entities can proceed because each waits for another member, including itself, to take action, such as sending a message or, more commonly, releasing a lock -A deadlock situation on a resource can arise only if all of the following conditions occur simultaneously in a system: -1. _Mutual exclusion:_ At least one resource must be held in a non-shareable mode; that is, only one process at a time can use the resource. Otherwise, the processes would not be prevented from using the resource when necessary. Only one process can use the resource at any given instant of time. -2. _Hold and wait_ or _resource holding:_ a process is currently holding at least one resource and requesting additional resources which are being held by other processes. -3. _No preemption:_ a resource can be released only voluntarily by the process holding it. -4. _Circular wait:_ each process must be waiting for a resource which is being held by another process, which in turn is waiting for the first process to release the resource. In general, there is a set of waiting processes, _P_ = {_P_1, _P_2, …, _P__N_}, such that _P_1 is waiting for a resource held by _P_2, _P_2 is waiting for a resource held by _P_3 and so on until _P__N_ is waiting for a resource held by _P_1._ -These four conditions are known as the _Coffman conditions_ from their first description in a 1971 article by Edward G. Coffman, Jr. -While these conditions are sufficient to produce a deadlock on single-instance resource systems, they only indicate the possibility of deadlock on systems having multiple instances of resources. - -Eliminate deadlock -1. detect cycle by dfs or cutting branches -2. try all the possible allocation patterns -detection: (find deadlocks happening)banker's algorithm -avoidance: (avoid deadlocks at most extent)resource trajectories (check point and roll back) -prevention: (remove conditions, definitely no deadlock) -1. attack circular waiting condition - 1. mutial exclusion: spool everything and hide the resources - 2. hold and wait:request all the rescources intially - 3. preemption: take resources away - 4. circular wait: order all the resources numerically -busy waiting: livelock -signal : deadlock \ No newline at end of file diff --git "a/dongshen/\344\270\255\346\226\255\345\222\214\345\274\202\345\270\270.md" "b/dongshen/\344\270\255\346\226\255\345\222\214\345\274\202\345\270\270.md" deleted file mode 100644 index 2f86a8d..0000000 --- "a/dongshen/\344\270\255\346\226\255\345\222\214\345\274\202\345\270\270.md" +++ /dev/null @@ -1,204 +0,0 @@ -[[特权级]] -[[硬件中断和软件中断 硬中断和软中断]] -[[操作系统期末考试]] -中断是由硬件支持、软件配合做的 -中断向量表:表里面全部是jump 跳到中断处理代码的位置。 -发生中断的时候加上一个offset到表中找到jump函数,进行跳转 -### 上下文切换 -中断时期上下文为进程保持完全相同,理想情况下只需要保证寄存器的状态和内存的状态,但是缓存的状态如果发生了改变会暴露了上下文已经被切过了。 -由于上下文切换需要保证内存上下文一致,**会访问到页表**,因此上下文切换必须有**内核态**来做。 -为了减少上下文切换的开销,需要进行一些优化: -1. 一个是扫描寄存器的使用,如果是 没有用到的寄存器,就不进行load、store操作。 -2. syscall merge,如果两个syscall之间的间隔足够,可以把这段不太长的时间等待过去。 - syscall batching,就像store buffer一样,记下每一个syscall的操作,攒一个batching慢慢的做,只要保证静态分析中做的事情是相同的,就能保证这么多syscall按照原来的顺序是正确的。甚至会在内核中做一些常数传播的编译优化。 - _syscall merge的问题:_ - - 导致内核的膨胀,内核要记录太多的处理信息 - - 导致内核的安全问题,别的进程可以通过内核的信息得知别的进程的信息 - - 导致内核危害,内核要做的事情太多 - -#### 为什么需要中断/异常机制,目的是什么 - -一下特性是中断和异常分别提供的: - -- **支持cpu和设备之间的并行**(在有需要时记下当前的状态,转而执行响应的事件处理程序,待处理完成后再返回断点或调度其他程序) -- **实时交互的需要**(即刻响应,响应之后还能返回断点继续执行) -- **优先级支持**(对更紧急任务的支持) -- **故障报警与处理** -- **保护性操作需要,防止破坏**(在进入内核态时发生中断,发生权限变化,处理完内核态任务之后再改变权限返回,保护内核) -- **并行和进程操作/交互的需要**(时间片) - -#### 中断和异常的区别 - -从发生源角度和处理方式角度划分为了中断和异常. 但是他们处理问题的方式和思路本质是一样的. - -中断指I/O设备发出,也成为外中断.外部事件 -异常是正在执行的指令引发的,cpu执行指令本身出现问题=>响应错误/异常处理程序,执行系统调用(通过trap) - -中断解决cpu和设备间并行操作;异常解决cpu执行指令时出现的问题处理(算数溢出/地址越界...) - -外中断,也是中断,异步中断,是指来自处理器之外的中断信号,包括时钟中断、键盘中断、它机中断和外部设备中断。外中断又分==可屏蔽中断==和==不可屏蔽中断==,各个中断具有不同的优先级,表示事件的紧急程度,==在处理高一级中断时往往会部分或全部屏蔽低级中断==。因最开始的中断仅针对外中断,因此外中断也直接称作中断。 - -内中断,又称异常,同步中断,是指来自处理器内部的中断信号,通常是由于在程序执行过程中,**发现与当前指令关联的、不正常的或错误的事件**。==内中断不能被屏蔽,一旦出现必须立即予以响应并进行处理==,只是处理程序运行过程中可以选择是否屏蔽其它中断或屏蔽哪些中断。 内中断可细分为: -* 访管中断,由系统程序执行访管指令引起,可以看做机器指令的一种扩充; -* 硬件故障中断,如:电源失效、奇偶校验错误,总线超时; -* 程序性中断,如:非法操作、地址越界、页面故障、调试指令、除数为0和浮点溢出等。 - -中断由外部的中断控制器进行触发和响应. -异常由cpu内部的中断处理器电路控制. - -中断和异常的区别 -![[Pasted image 20230223094133.png]] -关于它们的区别有两点是需要注意的: -平常所说的屏蔽中断是不包括异常的,即异常不会因为CPU的IF位被清(关中断,指令:cli)而受影响,比如缺页异常,即使关了中断也会触发CPU的处理,回答了我上面红色部分疑问。 -通常说的int 80h这种系统调用使用的中断方式实际上硬件上是理解为异常处理的,因此也不会被屏蔽掉,这也很好理解,int 80h这种中断方式是程序里主动触发的,对于CPU来说属于同步事件,因此也就属于异常的范畴。 - -### 为什么中断处理过程中不能被阻塞,而异常处理过程却可以? - -这是一个从解决问题考虑的设计思路问题,中断是外部设备发出, 你没办法决定是否可以忽略,所以只能立刻响应, 至于做不做事是可以决定的. -异常所提供的服务本就是当前进程所需要的,故而当进程需要阻塞的时候,便会在异常处理程序中设置阻塞。所以它是你自己可控的你可以决定它是否可以阻塞. - -## 中断/异常分类 - -图1 - - - - - -![](https://pic1.zhimg.com/80/v2-2003613a2b6bb8be504675c79dbc8a54_720w.webp) - - -Scannable Document on Jan 6, 2021 at 9_18_46 AM.png - -按中断源进行分类:发出中断请求的设备称为中断源。按中断源的不同,中断可分为 -内中断:即程序运行错误引起的中断 -外中断:即由外部设备、接口卡引起的中断 -软件中断:由写在程序中的语句引起的中断程序的执行,称为软件中断 - -允许/禁止(开/关)中断: CPU通过指令限制某些设备发出中断请求,称为屏蔽中断。从CPU要不要接收中断即能不能限制某些中断发生的角度 ,中断可分为 -可屏蔽中断 : -可被CPU通过指令限制某些设备发出中断请求的中断, 那是不是意味着进中断时disable整个中断,其实disable的都是可屏蔽中断? -不可屏蔽中断: -不允许屏蔽的中断如电源掉电 - -可屏蔽中断, -I/O设备发出的所有中断请求(IRQ)都产生可屏蔽中断,一个屏蔽的中断只要还是屏蔽的,控制单元就可以忽略它。 -非屏蔽中断,有一些危险的事件才能引起非屏蔽中断,例如硬件故障,非屏蔽中断总是由CPU辨认。 - -## 中断/异常工作机制 - -硬件软件同时支持才能完成. -由硬件捕获响应,软件识别类型然后处理. -每个中断/异常都有个号码,由硬件设计者或者操作系统设计者定义 - -大致流程: -硬件捕获中断(某个针脚高电压)->根据内容按规矩编码(中断码)->写入中断寄存器 -cpu执行指令周期的最后时刻扫描中断寄存器->暂停当前程序->保护现场->根据中断码去中断向量表查询->找到地址及相关状态参数->执行中断程序->恢复 - -## 中断/异常的软硬件支持结构 - -os: -操作系统设计时,提前设置中断/异常处理程序和向量表 -设计和实现中断处理程序 -设计处理程序的向量表 -运行时响应中断 - -中断码: 中断硬件对中断内容按规则编码,送入程序状态字寄存器(PSW)的相应位 中断向量表: 硬件查的表 映射中断处理程序 中断向量: 它是内存单元 存储处理程序入口地址,程序运行所需的处理机状态字 - -硬件: -中断寄存器: -保存中断信号 -cpu响应: -在指令执行周期最后时刻扫描中断寄存器,看是否有 -判断是否允许中断 - -硬件的工作:(捕获/响应) -* 捕获中断源请求 -* 响应 -* 控制权交给特定处理程序 -软件的工作:(处理) -* 识别中断/异常类型 -* 完成处理(软件本身为处理程序) - -## 实施/保护模式 - -在X86中,分为实模式和保护模式,实模式通常是CPU启动到BIOS再到操作系统启动前的这段时间,操作启动初始化完成进入到保护模式。 - -## 补充知识 - -常见异常: - -- 算数溢出 -- 除零 -- 取数奇偶校验错 -- trap指令(system call) -- 硬件改变cpu执行流程 -- 地址越界 -- 页错误/故障 -- 保护性异常(写仅读内存) -- 断点指令 - -常见中断: - -- I/O中断 -- 时钟中断 -- 硬件故障 - -图2 - -中断允许触发器:在CPU内部设置一个中断允许触发器,只有该触发器置“1”,才允许中断;置“0”,不允许中断。 - -指令系统中,开中断指令,使中断触发器置“1” 关中断指令,使中断触发器置“0” - -中断优先级:为了管理众多的中断请求,需要按每个(类)中断处理的急迫程度,对中断进行分级管理,称其为中断优先级。在有多个中断请求时,总是响应与处理优先级高的设备的中断请求。 - -中断嵌套:当CPU正在处理优先级较低的一个中断,又来了优先级更高的一个中断请求,则CPU先停止低优先级的中断处理过程,去响应优先级更高的中断请求,在优先级更高的中断处理完成之后,再继续处理低优先级的中断,这种情况称为中断嵌套。 - -中断又可以分为可屏蔽中断和非可屏蔽中断, -中断屏蔽是指 禁止 CPU 响应或禁止中断产生。前者是指 CPU 暂时不响应中断,等中断开放了被屏蔽的中断才能被响应,防止同级或高级的中断影响。后者是中断的事件发生时直接不允许提出中断请求也不能通知 CPU。 - -多重中断有几种处理方法,一种是串行处理,CPU 响应中断的时候屏蔽其它部分或所有中断;第二种是即时处理,运行中断的过程中,如果出现程序性中断(异常),一般情况表明此时中断处理程序有异常,应对其进行立即响应;第三种是嵌套处理,对于有些必须处理的高优先级的中断事件,采用屏蔽的方法不妥,因此允许某些中断处理程序时依然能够响应中断。操作系统必须预先规定每类中断的优先级,中断嵌套一般不会超过 3 重,过多嵌套会增加系统不必要的开销。 - -## 系统调用 - -系统调用使用trap实现, 是用户态到内核态的唯一入口(调用操作系统接口使用特权指令) -特殊指令: -是trap/访管指令,调用不同系统接口的统一入口,根据号和参数区分 -流程: -通过trap一发异常-> 用户态切换到内核态->传参执行 - -### 用户参数如何传入内核 - -三种方式: - -1. trap指令自带参数(数量有限) -2. 通用寄存器,通用方案,寄存器个数有限 -3. 内存中专门对战区 - -### 地址空间 -地址空间的约定:一般用户和内核的地址空间在相差比较大的地方。cache攻击 -MMIO PIO -Memory Map IO and Port IO -内核嵌套中断 -page fault是异常 -异常向量表的设置:CPU上电之后立即执行,是系统初始化的主要工作之一,在开启中断和启动第一个应用之前。 -内核运行的时候可能会有嵌套中断: -1. 内核执行过程中发生了缺页(用户的地址和内核相差很多的目的就是尽量减少内核的页表被swap) -2. 内核执行过程中出现外部设备中断 -3. 内核接收到别的核的用户程序主动发的syscall -![[SYSCALL传参数.jpg]] -但是用户态可以利用构造一个非法的指针,通过syscall攻击内核,内核翻译这些虚拟地址时就会造成各种问题,于是内核就会做相应的检查,防止出现一个未映射区域或者非法访问,如果是page fault,直接帮它call swap page就行 -FixSC:flexible syscall,如果有多出来的核,可以给用户和内核各一个数据页,拿出一个核专门做在内核和用户态之间传递相关数据,避免syscall的开销; - -## 时钟中断 -时钟中断(Clock Interrupt)是一种计算机硬件中断,它是由 CPU 内部的硬件定时器产生的,用于确保操作系统和应用程序在运行过程中能够获得适当的时间片并进行调度。 - -当 CPU 启动时,定时器开始计数。当定时器的计数值达到预设的阈值时,CPU 就会产生一个时钟中断。时钟中断会暂停正在执行的进程,并将 CPU 的控制权移交给操作系统内核来处理。在内核中,时钟中断通常被用来执行以下几个任务: - -1. 时间管理:时钟中断可以帮助操作系统跟踪时间的流逝,从而保证正确地记录日志、备份数据等。 -2. 进程调度:时钟中断可以触发进程调度,使得操作系统能够按照特定的算法决定哪些进程获得 CPU 的使用权。 -3. 虚拟内存管理:时钟中断可以触发虚拟内存管理机制,从而允许操作系统重新分配页面并回收未使用的内存。 - -时钟中断的频率通常是固定的,且与 CPU 的主频有关。例如,在一个 1 GHz 的 CPU 上,时钟中断通常以每秒 1000 次的速度运行。操作系统可以根据需要调整时钟中断的频率,以实现更好的性能和功耗平衡。 - -总之,时钟中断是计算机硬件中的一种机制,它可以帮助操作系统跟踪时间的流逝、执行进程调度和虚拟内存管理等任务。 \ No newline at end of file diff --git "a/dongshen/\347\241\254\344\273\266\344\270\255\346\226\255\345\222\214\350\275\257\344\273\266\344\270\255\346\226\255 \347\241\254\344\270\255\346\226\255\345\222\214\350\275\257\344\270\255\346\226\255.md" "b/dongshen/\347\241\254\344\273\266\344\270\255\346\226\255\345\222\214\350\275\257\344\273\266\344\270\255\346\226\255 \347\241\254\344\270\255\346\226\255\345\222\214\350\275\257\344\270\255\346\226\255.md" deleted file mode 100644 index 0065272..0000000 --- "a/dongshen/\347\241\254\344\273\266\344\270\255\346\226\255\345\222\214\350\275\257\344\273\266\344\270\255\346\226\255 \347\241\254\344\270\255\346\226\255\345\222\214\350\275\257\344\270\255\346\226\255.md" +++ /dev/null @@ -1,29 +0,0 @@ -[[API]] -中断机制:CPU在执行指令时,收到某个中断信号转而去执行预先设定好的代码,然后再返回到原指令流中继续执行,这就是中断机制 -### software interruption -A software interrupt is a type of interrupt ==generated by software, rather than a hardware device==, in a computer system. It is used to request a service or notify the operating system kernel of an event. -When a software interrupt is generated, the CPU suspends the execution of the current program and switches to kernel mode to execute a corresponding software interrupt handler routine. -Software interrupts are often used by ==applications to communicate with the operating system or to **request services from the kernel==** -### hardware interruption -A hardware interrupt is a signal generated by a hardware device. -When a hardware interrupt occurs, the CPU stops the current task it is executing and switches to a special mode called ==interrupt mode== to handle the interrupt. The processor saves the current program state and registers, and then jumps to the appropriate ==interrupt handler routine==, which is **a small section of code** designed to handle the specific interrupt. -### softirq -Like hardware interrupts, softirqs are a type of interrupt that can **preempt the normal execution of the kernel and execute an interrupt handler routine** and has its own context. However, unlike hardware interrupts, softirqs are **generated by software**, not hardware devices. -A softirq is a mechanism used by the Linux kernel to handle deferred processing tasks that **require a high priority but cannot be handled directly in hardware interrupts**. -==used by the kernel to handle **high-priority** tasks that cannot be handled directly in hardware interrupts due to their complexity or overhead.== -Softirq handlers are executed in a **preemptive manner,** which means that they can be interrupted by higher-priority softirqs or hardware interrupts. This allows the kernel to handle high-priority tasks in a timely and efficient manner while maintaining system responsiveness and throughput. -硬件中断和硬中断一样 -#### 中断的来源(区分软件/硬件中断) -1.外设,外设产生的中断信号是异步的,一般也叫做**硬件中断(** 注意硬中断是另外一个概念)。硬件中断按照是否可以屏蔽分为可屏蔽中断和不可屏蔽中断。例如,网卡、磁盘、定时器都可以产生硬件中断。 - -2.CPU,这里指的是一个CPU向另一个CPU发送中断,这种中断叫做IPI(处理器间中断)。IPI也可以看出是一种特殊的**硬件中断**,因为它和硬件中断的模式差不多,都是异步的。 - -3.CPU异常,CPU在执行指令的过程中发现异常会向自己发送中断信号,这种中断是同步的,一般也叫做**软件中断(由软件比如应用程序和操作系统来发起)** (注意软中断是另外一个概念)。CPU异常按照是否需要修复以及是否能修复分为3类:1.==陷阱(==trap),不需要修复,中断处理完成后继续执行下一条指令,2.==故障==(fault),需要修复也有可能修复,中断处理完成后重新执行之前的指令,3.==中止==(abort),需要修复但是无法修复,中断处理完成后,进程或者内核将会崩溃。例如,缺页异常是一种故障,所以也叫缺页故障,缺页异常处理完成后会重新执行刚才的指令。 -4.中断指令,直接用CPU指令来产生中断信号,这种中断和CPU异常一样是同步的,也可以叫做软件中断。例如,中断指令int 0x80可以用来实现系统调用。 - -#### 中断的作用 -设计中断机制的目的在于中断机制有以下4个作用,这些作用可以帮助操作系统实现自己的功能。这四个作用分别是: -**1.外设异步通知CPU:** 外设发生了什么事情或者完成了什么任务或者有什么消息要告诉CPU,都可以异步给CPU发通知。例如,网卡收到了网络包,磁盘完成了IO任务,定时器的间隔时间到了,都可以给CPU发中断信号。 -**2.CPU之间发送消息:** 在SMP系统中,一个CPU想要给另一个CPU发送消息,可以给其发送IPI(处理器间中断)。 -**3.处理CPU异常:** CPU在执行指令的过程中遇到了异常会给自己发送中断信号来处理异常。例如,做整数除法运算的时候发现被除数是0,访问虚拟内存的时候发现虚拟内存没有映射到物理内存上。 -**4.实现系统调用:** 早期的系统调用就是靠中断指令来实现的,后期虽然开发了专用的系统调用指令,但是其基本原理还是相似的。 \ No newline at end of file diff --git "a/dongshen/\347\272\277\347\250\213 \350\277\233\347\250\213.md" "b/dongshen/\347\272\277\347\250\213 \350\277\233\347\250\213.md" deleted file mode 100644 index 288364e..0000000 --- "a/dongshen/\347\272\277\347\250\213 \350\277\233\347\250\213.md" +++ /dev/null @@ -1,169 +0,0 @@ -[[操作系统期末考试]] -线程、进程和协程都是计算机程序中常用的并发编程模型,它们之间有以下几个区别: -1. 资源分配:进程是操作系统资源分配的基本单位,包括代码、数据、堆栈等,**每个进程都有独立的内存空间和系统资源**。而线程是进程的一个执行单元,**同一进程中的线程共享相同的内存空间和系统资源,并且可以独立运行,但线程之间的切换开销比进程小。** -2. 执行方式:进程和线程都是**抢占式调度**的,由操作系统负责调度,其执行方式是由操作系统控制的。而协程是**协作式调度**的,由程序员手动控制切换(Yield),其执行方式可以更加高效和灵活。 -3. 上下文切换:进程之间切换会涉及到大量的上下文切换、内存映射等操作,开销较大;线程之间切换开销相对较小;而协程的切换只需要保存少量上下文信息,开销最小。 -4. 编程复杂度:进程和线程在编程时需要考虑同步、互斥、死锁等问题,编程复杂度较高;而协程相对于进程和线程来说,编程复杂度较低,但需要手动管理协程状态,编写的程序需要遵循协作式的调度逻辑。 -5. 应用场景:进程通常用于分布式系统、操作系统等底层应用;线程一般用于网络服务、GUI编程等中层应用;协程通常用于高并发的服务器、游戏开发等上层应用。 -总之,进程、线程和协程都是计算机程序中常用的并发编程模型,它们各有特点,在不同的应用场景下可以选择合适的模型来实现高效并发编程。 -## System Call -Linux基础系统调用(syscall)是用户空间程序与内核之间的接口,通过系统调用可以让用户空间程序请求内核提供的服务,如文件操作、进程管理、网络通信等。在Linux中,系统调用通常使用软中断(software interrupt)方式实现。下面是Linux基础syscall的执行过程: - -1. 用户空间程序通过指令int 0x80或sysenter**将控制权交给内核**; -2. CPU检测到中断并转入内核模式,保存用户态寄存器的值,并切换到内核态栈; -3. 内核根据传入的系统调用号,在系统调用表中查找相应的系统调用函数,并保存系统调用参数; -4. 系统调用函数根据参数进行处理,并返回系统调用结果; -5. 内核从系统调用返回,并将返回值存放在寄存器中; -6. CPU切换回用户态,将返回值传递给用户空间程序。 -当使用sysenter指令进行系统调用时,可以绕过中断向量表的查找和处理过程,从而提高系统调用的执行效率。这里的关键在于,**在Linux内核启动时,会初始化中断向量表,并将所有的系统调用对应的中断号和中断处理函数的入口地址进行映射**。因此,当使用sysenter指令进行系统调用时,内核可以直接从该映射表中获取对应的中断处理函数的入口地址,从而实现快速执行。 -需要注意的是,系统调用是一种特殊的函数调用,涉及到用户态和内核态之间的切换,因此系统调用会带来额外的开销。为了减少这种开销,Linux提供了一些优化技术,如vDSO(virtual dynamic shared object)和seccomp(secure computing)机制等,使得系统调用的执行更加高效、安全和可靠。 - -### fork -**fork** is an operation whereby a process **creates a copy of itself.** -It is usually implemented as a C standard library wrapper to the fork, clone, or other system calls of the kernel. -For a process to start the execution of a different program, it first forks to create a copy of itself, creating a child process. **Then the child calls `exec` system call to overlay itself**: it ceases execution of its former program in favor of the other. -The fork operation creates **a separate address space** for the child. The child process **has an exact copy of all the memory segments of the parent process**. -copy-on-write semantics are implemented and the physical memory need **not be actually copied**. Instead, virtual memory pages in both processes may refer to the same pages of physical memory **until one of them writes to such a page: then it is copied**. This optimization is important in the common case where the child process performs only a small set of actions before it ceases execution of its program in favour of the program to be started, and it requires very few, if any, of its parent's data structures. -hey can then inspect the call's **return value to determine their status, child or parent**, and act accordingly. child returns 0, parent returns the mark of child processes. -子进程从父进程的文件描述符副本开始。对于进程间通信,父进程通常会创建一个或多个管道,在fork进程之后,进程关闭它们不需要的管道端。 -在发出一个**vfork**系统调用时,父进程被暂停,直至子进程完成执行或被新的可执行映像取代(通过系统调用之“exec”家族中的一项)。子进程借用父进程的MMU设置和内存页面,在父进程与子进程之间共享,不进行复制,如果子进程在任何共享页面中进行修改,不会创建新的页面,并且修改的页面对父进程同样可见。父进程会等待子进程执行,直到子进程调用`exec`创建自己的独立地址空间或者执行完退出为止。因为没有页面复制(消耗额外的内存),此技术在纯复制环境中使用exec时较普通fork更优化。 -### exec -In computing, `exec` is a functionality of an operating system that **runs an executable file in the context of an already existing process, replacing the previous executable**. This act is also referred to as an **overlay**. It is especially important in Unix-like systems, although it exists elsewhere. As no new process is created, the process identifier **(PID) does not change**, but the machine code, data, heap, and stack of the process are replaced by those of the new program. - -A file descriptor open remains open when an exec call is made in the new process image, unless was `fcntl`ed with `FD_CLOEXEC` or opened with `O_CLOEXEC` (the latter was introduced in POSIX.1-2001). This aspect is used to specify the standard streams (stdin, stdout and stderr) of the new program. -A successful overlay **destroys the previous memory address space of the process,** and all its memory areas, that were not shared, are reclaimed by the operating system. Consequently, all its data that were not passed to the new program, or otherwise saved, become lost. -A successful exec replaces the current process image, so it cannot return anything to the program that made the call. Processes do have an exit status, but that value is collected by the parent process. -If an exec function does return to the calling program, an error occurs, the return value is −1, -### wait -In computer operating systems, a process (or task) may wait for another process to complete its execution. In most systems, a parent process can create an independently executing child process. The parent process may then issue a `wait` system call, which suspends the execution of the parent process while the child executes. **When the child process terminates, it returns an exit status to the operating system, which is then returned to the waiting parent process.** The parent process then resumes execution. -An operating system may provide variations of the wait call that allow a process to wait for any of its child processes to exit, or to wait for a single specific child process (identified by its process ID) to exit. -**Some operating systems issue a signal (`SIGCHLD`) to the parent process when a child process terminates,** notifying the parent process and allowing it to get the child process's exit status. -The exit status returned by a child process typically indicates whether the process terminated normally or abnormally. For normal termination, this status also includes the exit code (usually an integer value) that the process returned to the system. -When a child process terminates, it becomes a **zombie** process, and continues to exist as an entry in the system process table even though it is no longer an actively executing program. Under normal operation it will typically be immediately waited on by its parent, and then reaped by the system, **reclaiming the resource** (the process table entry). If a child is not waited on by its parent, it continues to **consume this resource indefinitely, and thus is a resource leak.** Such situations are typically handled with a special **"reaper" process** that locates zombies and retrieves their exit status, allowing the operating system to then deallocate their resources. -Conversely, a child process whose parent process terminates before it does becomes an orphan process. Such situations are typically handled with a special "root" (or "init") process, **which is assigned as the new parent of a process when its parent process exits**. This special process detects when an orphan process terminates and then retrieves its exit status, allowing the system to deallocate the terminated child process. -### exit -On many computer operating systems, a computer process terminates its execution by making an exit system call. More generally, an exit in a multithreading environment means that a thread of execution has stopped running. For resource management, the operating system **reclaims resources** (memory, files, etc.) that were used by the process. The process is said to be a dead process after it terminates. -Under Unix and Unix-like operating systems, a process is started when its parent process executes a **fork** system call. The parent process may then **wait** for the child process to terminate, or may continue execution (**possibly forking off other child processes**). When the child process terminates ("dies"), either normally by calling exit, or abnormally due to a fatal exception or signal (e.g., SIGTERM, SIGINT, SIGKILL), an exit status is returned to the operating system and a SIGCHLD signal is sent to the parent process. The exit status can then be retrieved by the parent process via the **wait** system call. As the final step of termination, a primitive system exit call is invoked, **informing the operating system that the process has terminated and allows it to reclaim the resources used by the process.** That is the subroutine of cleanup -### kill(信号) --9是信号 -kill is a command, not a sys call. -But kill is something of a *misnomer(误称)*; **the signal sent may have nothing to do with process killing**. The kill command is a wrapper around the `kill()` system call, which sends signals to processes or process groups on the system, referenced by their numeric process IDs (PIDs) or process group IDs (PGIDs). -There are many different signals that can be sent.  The default signal sent is `SIGTERM`. ->**SIGINT** "Signal interrupt" The SIGINT signal is sent to a process by its controlling terminal when a user wishes to **interrupt** the process. This is typically initiated by pressing Ctrl+C ->**SIGKILL** "Signal kill" The SIGKILL signal is sent to a process to cause it to **terminate immediately (kill)**. In contrast to SIGTERM and SIGINT, this signal **cannot be caught or ignored, and the receiving process cannot perform any clean-up upon receiving this signal**. ->**SIGTERM** "Signal terminate" The SIGTERM signal is sent to a process to request its **termination**. Unlike the SIGKILL signal, it **can be caught and interpreted or ignored by the process.** This allows the process to perform nice termination **releasing resources and saving state if appropriate**. SIGINT is nearly identical to SIGTERM. - -## Handler -系统调用syscall()可以用来**注册或修改信号处理程序**。它的函数原型为: - -```c -#include -#include - -long syscall(long number, ...); -``` - -其中,第一个参数number指定了要执行的系统调用号,后面的...表示该调用需要传入的参数列表。 -在使用syscall()注册或修改信号处理程序时,需要使用sigaction()函数设置信号的处理方式、信号的被阻塞和解除阻塞时的行为等;signal()函数则设置信号的处理方式,但比较简单,只有两种处理方式:忽略信号或者执行默认的信号处理函数。 -在信号处理程序被注册后,当系统产生一个信号时,内核就会向相应的进程发送这个信号,并将信号处理程序与该信号关联起来。当进程接收到信号时,会执行与信号关联的信号处理程序。 -```C -#include -#include - -void sigterm_handler(int signum) { - printf("Received SIGTERM signal, terminating...\n"); - // ...执行一些清理工作... - exit(0); -} - -#include -#include -#include -#include - -int main() { - struct sigaction sa; - sa.sa_handler = sigterm_handler; // 设置信号处理函数 - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - - if (sigaction(SIGTERM, &sa, NULL) == -1) { - perror("sigaction error"); - exit(1); - } - - // ...执行一些其他操作... - // 调用syscall()执行需要修改的系统调用 - syscall(SIGTERM, args); - - return 0; -} - -#include -#include -#include -#include - -int main() { - signal(SIGTERM, sigterm_handler); // 设置信号处理函数 - - // ...执行一些其他操作... - // 调用syscall()执行需要修改的系统调用 - syscall(SIGTERM, args); - - return 0; -} - -``` -### vsyscall -一些不太敏感的系统调用放到用户态来做,确保安全的情况下更加性能。 - -## syscall ABI -在Linux系统中,当应用程序调用syscall时,其返回值通常存储在EAX寄存器中,即%eax。 -在x86架构的Linux系统中,syscall使用的是系统调用号(system call number)标识需要执行的系统调用。系统调用号和参数都会被存储在寄存器中,例如使用EAX寄存器来存储系统调用号,EBX、ECX、EDX、ESI等寄存器来存储系统调用的参数。 -对于x86_64架构的系统,则使用RAX寄存器来存储系统调用号,而将其他系统调用参数放置在RDI、RSI、RDX、R10、R8以及R9等寄存器中。系统调用结束后,操作系统会将返回值保存在RAX寄存器中,应用程序可以通过读取RAX寄存器的值来获得系统调用的返回值。 - -因此,针对不同的系统架构,我们可以根据对应的ABI(Application Binary Interface,应用二进制接口)规范来获取syscall的返回值。在每种架构的系统中,ABI都会规定如何使用寄存器来传递参数、如何进行函数调用和返回值处理等细节,从而确保不同的应用程序能够在相同的系统环境中运行并交互。 - -##### 如果并行线程过多,可能会出现以下性能问题: -1. **上下文切换开销增加**:当线程数量增加时,操作系统需要频繁地进行线程之间的上下文切换,将CPU资源分配给不同的线程。但是,上下文切换本身也会产生一定的开销,因此过多的线程会导致系统的运行效率降低。 -2. **内存和缓存争用**:每个线程都需要占用一定的内存空间和CPU缓存,如果线程数目过多,可能会导致内存和缓存的争用情况加剧,从而导致性能下降。 -3. **线程阻塞和竞争条件**:线程之间可能存在相互依赖和共享资源的情况,如果线程数目过多,就容易出现线程之间的**阻塞**和**竞争条件**,从而影响程序的稳定性和可靠性。 -4. **调度延迟和饥饿现象**:在多核处理器中,线程之间可以并行执行,但是调度过程也需要时间,如果线程数目过多,就容易出现调度延迟和**饥饿**(一次拿到所有需要的资源) 现象,导致某些线程无法得到充分的CPU资源。 - -为了避免上述问题,应该尽可能控制并行线程的数量,并根据实际情况进行优化调整。例如,可以使用线程池技术来控制线程的数量和生命周期,减少不必要的上下文切换和内存开销;还可以使用锁和同步机制来避免竞争条件和阻塞现象。总之,合理地控制并行线程的数量和调度,才能保证多线程应用程序的高效、稳定和可靠性。 - -##### 换页的开销 -在操作系统中,为了将物理内存资源充分利用,会使用虚拟内存技术来实现透明的内存管理。虚拟内存技术允许进程使用比其物理内存容量更大的虚拟地址空间,**当进程需要访问不在物理内存中的页面时,就会产生缺页中断(Page Fault),再从磁盘中读取所需页面到物理内存中,这个过程称为“换页”(Swap)。** - -在进行换页时,由于需要访问外部设备磁盘,因此会产生较大的开销,主要包括以下几个方面: -1. **I/O延迟**:读取磁盘数据是一个相对较慢的操作,通常涉及到磁盘寻道、旋转等机械操作,尤其是当磁盘请求队列较长或者磁盘故障时,I/O延迟会显著增加。 -2. **内存带宽开销**:当系统在进行页面置换时,需要将被置换出的页面写入到磁盘中,同时读取要置换的页面到内存中。这一过程需要**占用内存带宽,可能会影响其他正在运行的进程的性能**。 -3. CPU时间片浪费:当进程发生缺页中断时,操作系统需要暂停当前进程的执行,进行页面置换和I/O操作,直到磁盘数据读取完毕并完成页面替换后才能继续运行。当进程需要等待I/O操作、发生缺页中断、或者由于其他原因导致暂停执行时,**操作系统会将CPU资源分配给其他处于就绪状态的进程,直到当前进程再次准备好执行为止**。这种切换过程称为上下文切换(Context Switch),包括保存当前进程的状态和加载另一进程的状态,上下文切换也会有比较多的时间占用。 -4. 预取机制的不合理有可能会进一步拖累系统性能。空间本地性或者事件本地性不强的时候。 -因此,为了减少换页带来的开销,可以采取以下措施: -1. 增加物理内存:如果系统物理内存容量充足,就可以减少内存页面置换的频率,从而降低I/O延迟和内存带宽开销。 -2. 优化页面置换算法:选择合适的页面置换算法,如最近最少使用(LRU)算法、先进先出(FIFO)算法等,可以提高页面置换的效率,减少开销。 -3. 提高磁盘性能:通过提高磁盘读写速度、增加磁盘缓存、调整磁盘调度策略等方法,可以降低磁盘I/O延迟,提高页面读写效率。 -4. 减少进程数目和应用程序的内存占用:避免同时运行过多的进程和应用程序,可以减少页面置换的发生次数,降低CPU时间片的浪费。 - -总之,由于换页是一项关键的系统操作,它的开销会显著影响系统整体性能。因此,需要针对具体的应用场景和系统负载情况,选择合适的优化策略,以提高系统的性能和稳定性。 - -### LSCPU -超线程个数=逻辑CPU的个数 -![[Pasted image 20230531203129.png]] -**real 整个程序从开始到结束的时间。 -user 在用户态跑这个程序所用的时间,不包括被阻塞,在cpu上计算的时间。 -sys 处在内核态的时间。 -如果充分利用多核跑,real小于user -如果单核跑,real一般约等于user+sys,大于也可能 -如果是IO密集型/缺页很多,real远大于user** -sleep就是进入内核态把这个程序标记为被阻塞,到时间再来唤醒。中间cpuidle或者执行别的进程。sleep的时间不在user也不在sys(在内核标记、唤醒的时间非常短。) -## Turbo Boost of Intel -CPUs don’t always need to run at their maximum frequency. Some programs are more dependent on memory to run smoothly, while others are CPU-intensive. Intel® Turbo Boost Technology is an energy-efficient solution to this imbalance: **it lets the CPU run at its base clock speed when handling light workloads, then jump to a higher clock speed for heavy workloads.** -Running at a lower clock rate (the number of cycles executed by the processor every second) allows the processor to use less power, which can **reduce heat and positively impact battery life in laptops**. But when more speed is needed, Intel® Turbo Boost Technology dynamically increases the clock rate to compensate. This is sometimes called “algorithmic overclocking”. - -提高CPU频率可以提高运行速率的原因主要是增加了CPU的时钟周期,从而使得CPU在单位时间内可以处理更多的指令和数据。 -当 CPU 的时钟频率提高时,每个时钟周期的长度就会变短,CPU 可以在同样的时间内完成更多的指令执行。例如,如果一个 CPU 的时钟频率为 2GHz(即每秒钟有 20亿个时钟周期),那么每个时钟周期的长度约为 0.5 纳秒。如果将时钟频率提高到 4GHz,那么每个时钟周期的长度就缩短到了 0.25 纳秒,CPU 在同样的时间内可以执行更多的指令,从而提高运行速率。 -此外,提高 CPU 频率还可以使得 CPU 更快地读取和写入内存、缓存等数据结构,从而加快程序的执行速率。 -不过,需要注意的是,频率并不是唯一决定 CPU 性能的指标,还有很多其他因素如微架构设计、指令集支持等对 CPU 的性能有重要影响。同时,提高 CPU 频率也会带来一定的热量问题和功耗消耗问题,需要适当调节 CPU 的供电和散热系统以保证稳定性。 \ No newline at end of file diff --git "a/dongshen/\350\277\233\347\250\213\351\227\264\351\200\232\344\277\241.md" "b/dongshen/\350\277\233\347\250\213\351\227\264\351\200\232\344\277\241.md" deleted file mode 100644 index d7560bd..0000000 --- "a/dongshen/\350\277\233\347\250\213\351\227\264\351\200\232\344\277\241.md" +++ /dev/null @@ -1,16 +0,0 @@ -#### inter-process communication (IPC) -1. Pipes: between two processes running on the same machine. One process writes data to the pipe, and the other process reads from it. -2. Shared Memory: Shared memory is a technique that allows two or more processes to access the same area of memory. faster. -3. Message Queues: One process sends a message to a queue, and another process reads from the same queue to receive the message. -4. Sockets: communication by a network. One process establishes a socket, and the other process connects to it. -5. [[Semaphores]]: A semaphore is a synchronization tool that allows processes to synchronize access to a shared resource. It is often used in combination with shared memory to ensure that multiple processes can access the same memory area without conflicts. -#### reduce the conflicts in IPC ( or deal with Race Condition) -1. Mutual Exclusion: implemented using synchronization primitives such as **semaphores, mutexes, or locks**. When a process wants to access a shared resource, it first requests **the mutual exclusion lock**. If the lock is available, the process can proceed to access the resource. When it is done, it releases the lock so that another process can acquire it. If the lock is not available, the process waits until it becomes available. preventing conflicts in shared memory, critical sections, or other shared resources. - 保证临界区的操作都是原子操作 atomic operation -2. Synchronization: using synchronization primitives such as **signals, events, or barriers**. For example, memory barrier/ message queue `mb()` -3. Message Passing: using message queues, pipes, or sockets. When a process wants to send data to another process, it puts the data into a message or packet and sends it to the receiving process, preventing conflicts in situations where processes need to exchange data but should not access each other's memory directly. -4. Priority Scheduling: using scheduling algorithms that assign priorities to processes based on their importance or urgency. For example, a process that is handling critical data might be given a higher priority than a process that is handling non-critical data. -5. Resource Allocation: algorithms that allocate resources based on some criteria, such as the amount of resources required or the time required to complete a task. - - [[Mutual Exlusion]] - [[SD RSDL in Linux]]