os ch3
3.1 Process Concept
首先介绍进程(process)的概念:一个process指的是一个正在运行的程序
对于我的cpu而言,比如说我要运行一个程序,操作系统会将这个程序的可执行文件加载到内存中,上面的这张图片就展示了这个部分包括的各个内容:代码段、pc、寄存器、数据等等。而以下的一张图片就展现了我加载进来一个程序之后各个部分会如何分配:
记住一些:全局变量放在data段,函数内的局部变量放在stack;heap存放动态分配的内容
recall系统的调用(system call)的概念:一般的程序都执行在user mode,其具有的权限会相对比较低;而有时候其需要执行一个其还没有权限的指令的时候,这个时候就需要通过system call发送请求,切换到kernel mode完成相应的指令,之后再切换回user mode继续执行。
3.1.2 进程状态的转换
这个部分很好理解:关于I/O多说明一点,相当于当前我需要等待I/O之类的操作的时候,就要先放弃处理机,让别的进程来操作,其在I/O完成之后,相当于重新去排队(变成就绪),后面再看 整体结构如下:
也就是说 ready指的是现在在排队,排到了我直接就可以执行;而block指的是我需要等待一个信息或者事件发生之后(比如等待我想要的信息到了之后),我才变成可以执行的,进入ready状态 这里需要注意:如果有进程处于ready状态,那么就一定有进程在running状态
3.1.3 进程控制块(PCB)
进程控制块相当于我们实验中实现的那个struct,每一个进程对应着一个PCB,其中包含了和进程有关的各种信息,如图所示: 
相当于要保存当前进程的状态、id;以及我比如说刚才执行到io被挂起之后,需要记录刚才执行内容的“现场”信息
3.2 Process Scheduling
为了便于讨论,首先区分两种类型的进程:
3.2.3 Context Switch
上下文切换指的是:当我要将当前的进程切换为另外一个进程的时候,需要先保存当前进程的内容(到PCB),然后将新的进程的内容加载到内存执行的地方,如图所示:
上下文切换是一个纯粹的overhead(开销),因为其本身不做任何有意义的工作
3.3 Operations on Processes
对于这个部分,一个直观的总结如下:
3.3.2 Process Termination 进程终止
一般来说,一个进程终止的过程是这样的:因为主动或者被动的原因终止,然后调用操作系统的exit(),接着根据其为主动执行完的退出或者是异常,返回一个状态值给父进程的wait()然后释放资源;这个时候,有如下的两种情况: 1. 如果父进程没有调用wait,这个时候其状态值无法返回,就会成为“僵尸进程” 具体来说怎么理解?比如说子进程被kill了,但是当前时间父进程在忙(或者在sleep),比如说sleep了30s,在这段时间我的子进程已经dead了,但是记录我的信息的资源一直在等待父进程来阅读无法释放,成为了僵尸进程 2. 另一种情况是所谓的孤儿进程,这个指的是父进程先于我的子进程被kill了;这个时候我的子进程因为没有父进程来回收会一直处于一个僵尸状态,这显然是不合理的;一种解决方法是将所有这样的孤儿进程重新分配一个统一的父亲
3.4 Interprocess Communication(IPC)进程通信
定义了进程间的通信和协作进程,互相之间会交换信息,提供信息通信等等,通常有如下的两种实现方式: 共享内存(shared memory): 相比下面几种更快,需要用到 system call 的地方只有建立共享内存的时候; 消息传递(message passing): 在分布式系统中更容易实现,对于少量数据通信很有用(因为不需要处理冲突问题) 具体的看这页ppt
3.5 IPC in Shared-Memory Systems
对于shared memory类的系统,其主要的思想是让不同进程中做的修改可以同步到内存空间中(比如说,A B两个进程都要给sum加50,这时候A先加了50之后就需要将更新后的sum值同步到到内存,B再取值) 同时,另一个特点是所有communication均由进程而非操作系统调用
这是一个常见的范式模型:一个进程生产有用的信息,给到另一个进程可以进行使用
理解这段代码:有一个共享的buffer区域,两个指针in out分别指向下一个空闲槽位和下一个待消费的数据项;比如说当前in为0,那么放完一个之后,in会变成1;依此类推,在放完9个之后,in的值会返回0。具体的解释如下:
那么为什么会最多使用BUFFER_SIZE-1个数据?我们首先理解:当in=out=t的时候,代表t之前的数据全部是之前写过的数据,并且都已经被“消费”过了;而当恰好写满的时候,就无法区分当前数据是全部写满还是全部已经被消费过了(比如说消费者一个还没用,生产者已经写满了,这时候in回到0,out也是0)因此,一个常用的trick就是一直保留一个不用,让差一个写满的情况代表“写满”。
在这个背景下,对于consumer和customer的一种最简单的实现方式可以看ppt,大概就是是consumer有空位的时候就可以继续生产,写入队列,customer有没有读的内容的时候就可以继续下去读取数据
3.6 IPC in Message-Passing Systems
这个和上面的共享内存相比,不会共享一块很大的内存,而是离散地发送双方交流过程中需要的数据,双方之间通过send/receive进行交换数据
3.6.1 直接通信
因此,对于进行通信的两个进程之间也有如下的要求:
需要明确指明所有信息
3.6.2 间接通信
间接通信会通过一个mailbox(port)这样一个“中继器”来传递信息,也就是所有进程把信息给mailbox,同时是从其中获得信息,其通信链路具有如下的特征:
以及其基本的信息交换代码:
一个问题:如果ABC连接在同一个邮箱,这个时候A发送信息,那么理论上我们需要限制B和C只有一个可以接收到信息,这时候我们有如下的机制措施:
3.6.3 进程同步
进程之间的通信分为blocking和non-blocking两种;blocking必须等待到数据接收才可以发送下一个,non-blocking两端都无所谓。以及这里有三种链路的不同模式: