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