深入理解计算机系统 第八章 异常控制流 Part2 第二遍
第二遍读这本书,每周花两到三小时时间,能读多少读多少(这次看了第 508~530 页,共 23 页)
第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/10206004.html
进程是计算机科学中最深刻、最成功的概念之一。(尽管看了书中关于进程的很多描述,我还是理解不了这句话,不是说怀疑这句话的正确性,只是自己不能理解,或许以后看得多了就能理解了)
进程和应用程序的关系
“进程的经典定义就是一个执行中的程序的示例”
那么,是否可以将它们的关系类比于 Java 中的类和对象呢?类对应于应用程序,对象对应于进程
上下文的概念
上下文是由程序正确运行所需的状态组成的。这个状态包括存放在内存中的程序的代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。
每次运行程序时,操作系统会为此创建一个新的进程,然后在这个新进程的上下文中运行程序实例。
逻辑控制流
处理器的一个物理控制流可以被多个进程共享,即一个物理控制流可以拆分为由几个不同的进程控制的、在时间上不重叠的逻辑控制流
# 待了解
物理控制流和逻辑控制流是否可以联系到 CPU 的物理核和逻辑核?
进程的三个状态
1、运行
进程要么在 CPU 上执行,要么在等待被执行且最终会被内核调度
2、停止
进程的执行被挂起(suspended),且不会被调度。当收到 SIGSTOP、SIGTSTP、SIGTTIN 或者 SIGTTOU 信号时,进程就停止,并且保持停止直到它收到一个 SIGCONT 信号,在这个时刻,进程再次开始运行。(信号是一种软件中断的形式)
3、终止
进程永远地停止了。进程回音三种原因终止:(1)收到一个信号,该信号的默认行为是终止进程,(2)从主程序返回,(3)调用 exit 函数
注:
提到的几个信号的意思如下:
# 疑问
感觉“停止”状态跟“运行”状态的等待被执行阶段是一样的,这两者之间有什么差别吗?
从 8.1 节的最后一段提到了进程被抢占即被挂起,感觉跟这里的挂起对应不起来
并发、并发流、并行、并行流、时间片、时间分片
当两个或多个逻辑流在时间上有交叉时,我们称之为并发流,这两个或多个流被称为并发地运行。
多个流并发地执行的现象被称为并发(concurrency)。一个进程和其他进程轮流运行的概念成为多任务(multitasking)。一个进程执行它的控制流的一部分的每一个时间段叫做时间片(time slice)。因此,多任务也叫做时间分片(time slicing)。
并发流的思想与流运行的处理器核数或者计算机数无关。如果两个流在时间上重叠,那么它们就是并发的,它是并发流的一个真子集。如果两个流并发地运行在不同的处理器核或者计算机上,那么我们称它们为并行流(parallel flow),它们并行地运行(running in parallel),且并行地执行。
不太明白并发与并行的区别,先记住并行流是并发流的真子集吧,并行流一定是并发流,并发流不一定是并行流。
私有地址空间
私有地址空间是进程为每个程序提供的一种假象,好像它独占地使用系统地址空间。
其实这个私有地址空间好像也叫做虚拟内存,“虚拟”,顾名思义,并不是真实的物理内存。
但是,尽管私有地址空间是假象、是虚拟的,每个进程的实际占有的空间在这个进程被终止前都是不能被其他进程读写的。从这个意义上说,这个地址空间是私有的。
内核
内核即操作系统常驻内存的部分
用户模式、内核模式
1、关于模式位
之前理解错了,之前以为设置的模式位有各种值,现在看来,好像只有两种状态,设置了和没设置
设置了就是内核模式,没设置就是用户模式
2、权限
处于用户模式的进程不能执行特权指令,比如停止处理器、改变模式位,或者发起一个 I/O 操作。也不允许用户模式中的进程直接引用地址空间中内核区内的代码和数据。任何这样的尝试都会导致致命的保护故障。反之,用户程序必须通过系统调用接口间接地访问内核代码和数据。
3、所谓的内核模式
进程从用户模式变为内核模式的唯一方法是通过异常(中断、故障或者陷入系统调用)。当异常发生时,控制传递到异常处理程序,处理器将模式从用户模式变为内核模式。处理程序运行在内核模式中,当它返回到应用程序代码时,处理器就把模式从内核模式改回到用户模式。(我的理解:即,发生异常时,进程陷入内核模式,然而此时并不会让进程随意执行指令,而是处理器根据异常处理程序来在内核模式下做特定的事)
我的一点理解,不知道对不对
用户模式和内核模式都是隶属于进程的,可以看做进程的两种身份,内核(操作系统常驻内存的部分)既可以代表进程在用户模式下运行、也可以代表进程在内核模式下运行,但并没有一个单独的内核进程,即内核在做这些事情的时候,是借助的某个进程的名义。
fork
创建子进程,关于比较难理解的一次调用、两次返回,我的理解如下:
在调用 fork 之后,子进程立刻产生,且立刻获得与父进程相同的任何东西(PID除外),那么函数的返回值肯定也是有的,但是值不同,父进程返回的是子进程的PID,子进程返回的是PID
这么看,父进程和子进程有两个值不一样,一是fork返回的值不一样,一个是PID不一样
其他的值都一样(其他的虽然是副本、是不同对象,但值一样)
进程的生命周期:
被创建 → 运行或被挂起 → 终止 → 僵死进程 → 被回收(即,不存在)
进程的回收操作一般由其父进程发起
进程组
8.5.2 小节中提到了进程组的概念,第一次听到这个概念,进程组是进程的集合,每个进程都只属于一个进程组,很多命令可以直接以进程组为操作对象,操作目标进程组中的所有哦进程