这里有一些术语问题更多是由于历史事故造成的。
“线程”通常是指进程中的控制线程,并且可能(在这种情况下)表示“具有自己的堆栈的任务,但它与该堆栈中的其他线程共享对不在该堆栈上的所有内容的访问。同一保护域”。
“进程”倾向于指一个独立的“保护域”,它可能(并且在这种情况下确实)能够在其中拥有多个线程。给定两个进程 P1 和 P2,P1 影响 P2 的唯一方法(反之亦然)是通过某些特定定义的“通信通道”,例如文件、管道或套接字;通过“进程间”信号,如 Unix/Linux 信号;等等。
由于线程之间没有这种屏障,一个线程很容易干扰(破坏)另一个线程使用的数据。
所有这些都独立于用户与内核,但有一个例外:在“内核”中——请注意这里隐含假设只有一个内核——您可以访问始终保持整个机器状态,以及执行任何操作的完全权限。因此,您可以故意(或在某些情况下意外)忽略或关闭硬件保护,并弄乱“属于”其他人的数据。
这主要涵盖了第一季度的几个可能混淆的项目。至于第二季度,所问问题的答案是“它没有”。一般来说,因为线程不涉及(尽可能多的)保护,所以从一个线程切换到另一个线程更便宜:您不必(以任何方式)告诉硬件它不应再允许各种访问,因为线程T1 和 T2 具有“相同”的访问权限。然而,在进程之间切换,就像 P1 和 P2 一样,你“越过了保护屏障”,这有一些惩罚(实际的惩罚因硬件而异扩展操作系统编写者的技能)。
还值得注意的是,从用户模式到内核模式以及反之亦然,也跨越了一个保护域,这又会产生某种成本。
在 Linux 中,用户进程有多种方法可以创建线程数量,包括“POSIX 线程”(pthreads)和clone 调用(clone 的详细信息非常灵活,超出了这个答案的范围)。如果你想编写可移植的代码,你可能应该坚持使用 pthreads。
在 Linux 内核中,线程的处理方式完全不同,您需要 Linux 内核文档。
我无法正确回答 Q4,因为我没有这本书,也不确定他们在这里指的是什么。我的猜测是,它们的意思是,每当任何用户进程或线程进行“系统调用”(从操作系统请求某些服务)时,这都会越过用户/内核保护屏障,然后由内核来验证用户代码对该操作具有适当的权限,然后执行该操作。执行此操作的内核部分在内核级保护下运行,因此需要更加小心。
某些硬件(如今大多已过时)拥有(或拥有)不止两个级别的硬件提供的保护。在这些系统上,“用户进程”具有最少的直接特权,但在这些系统之上,您会发现“执行模式”、“系统模式”和(最高特权的)“内核”或“核心”模式。这些旨在降低穿越各种保护障碍的成本。在“执行”中运行的代码无法完全访问机器中的所有内容,因此它可以,例如,假设用户提供的地址是有效的,并尝试使用它。如果该地址实际上是无效的,则异常将上升到下一个更高级别。只有两个级别——“用户”,非特权;和“内核”,完全特权——内核代码必须非常仔细地编写。但是,如今可以以低成本提供“虚拟机”,这几乎已经过时了对多个硬件级别保护的需求。一个人只需编写一个真正的内核,然后让它以他们“认为”的“内核模式”运行其他东西。这就是 VMware 和其他“管理程序”系统所做的。