<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
    <channel>
      <title>🌰Senjl&#039;s Digital Garden🐉</title>
      <link>https://senjlearning.space</link>
      <description>最近的5条笔记 on 🌰Senjl&#039;s Digital Garden🐉</description>
      <generator>Quartz -- quartz.jzhao.xyz</generator>
      <item>
    <title>LLM-Weekly</title>
    <link>https://senjlearning.space/3-Research/2-LLM/LLM-Weekly</link>
    <guid>https://senjlearning.space/3-Research/2-LLM/LLM-Weekly</guid>
    <description><![CDATA[ &lt;h2 id=&quot;inference-accelerating&quot;&gt;Inference Accelerating&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#inference-accelerating&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;【Jun. 3nd】 &lt;a href=&quot;../../1-Theory/4-AI-Stack/03-LLM/_Wiki/Speculative-Decoding-vs-MTP&quot; class=&quot;internal alias&quot; data-slug=&quot;1-Theory/4-AI-Stack/03-LLM/_Wiki/Speculative-Decoding-vs-MTP&quot;&gt;LLM 推理加速技术系列（1）：投机解码与多词条预测&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt; ]]></description>
    <pubDate>Sun, 12 Apr 2026 18:00:22 GMT</pubDate>
  </item><item>
    <title>8-并发</title>
    <link>https://senjlearning.space/1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/8-%E5%B9%B6%E5%8F%91</link>
    <guid>https://senjlearning.space/1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/8-%E5%B9%B6%E5%8F%91</guid>
    <description><![CDATA[ &lt;h2 id=&quot;课后练习&quot;&gt;课后练习&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#课后练习&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;编程题&quot;&gt;编程题&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#编程题&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 Linux 环境中，基于 pthread 线程，有一系列的系统调用实现对应用程序的线程间同步互斥的支持。&lt;/p&gt;
&lt;p&gt;信号量是一种特殊的变量，可用于线程同步。它只取自然数值，并且只支持两种操作：P (SV): 如果信号量 SV 大于 0，将它减一；如果 SV 值为 0，则挂起该线程。V (SV)： 如果有其他进程因为等待 SV 而挂起，则唤醒，然后将 SV+1；否则直接将 SV+1。其系统调用为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;sem_wait (sem_t *sem)&lt;/code&gt;：以原子操作的方式将信号量减 1，如果信号量值为 0，则 sem_wait 将被阻塞，直到这个信号量具有非 0 值。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;sem_post (sem_t *sem)&lt;/code&gt;：以原子操作将信号量值 + 1。当信号量大于 0 时，其他正在调用 sem_wait 等待信号量的线程将被唤醒。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;互斥量：互斥量又称互斥锁，主要用于线程互斥，不能保证按序访问，可以和条件锁一起实现同步。当进入临界区 时，需要获得互斥锁并且加锁；当离开临界区时，需要对互斥锁解锁，以唤醒其他等待该互斥锁的线程。其主要的系统调用如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pthread_mutex_init&lt;/code&gt;: 初始化互斥锁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pthread_mutex_destroy&lt;/code&gt;： 销毁互斥锁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pthread_mutex_lock&lt;/code&gt;： 以原子操作的方式给一个互斥锁加锁，如果目标互斥锁已经被上锁，pthread_mutex_lock 调用将阻塞，直到该互斥锁的占有者将其解锁。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pthread_mutex_unlock&lt;/code&gt;: 以一个原子操作的方式给一个互斥锁解锁。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;条件变量: 条件变量，又称条件锁，用于在线程之间同步共享数据的值。条件变量提供一种线程间通信机制：当某个共享数据达到某个值时，唤醒等待这个共享数据的一个 / 多个线程。即，当某个共享变量等于某个值时，调用 signal/broadcast。此时操作共享变量时需要加锁。其主要的系统调用如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pthread_cond_init&lt;/code&gt;: 初始化条件变量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pthread_cond_destroy&lt;/code&gt;： 销毁条件变量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pthread_cond_signal&lt;/code&gt;： 唤醒一个等待目标条件变量的线程。哪个线程被唤醒取决于调度策略和优先级。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pthread_cond_wait&lt;/code&gt;： 等待目标条件变量。需要一个加锁的互斥锁确保操作的原子性。该函数中在进入 wait 状态前首先进行解锁，然后接收到信号后会再加锁，保证该线程对共享资源正确访问。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;** 在 Linux 环境下，请用信号量实现哲学家就餐的多线程应用程序。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;../../../../../1-Theory/3-System/03-Operating-System/Internal-and-design-principle/37-Dining-philosopher-impl&quot; class=&quot;internal&quot; data-slug=&quot;1-Theory/3-System/03-Operating-System/Internal-and-design-principle/37-Dining-philosopher-impl&quot;&gt;37-Dining-philosopher-impl&lt;/a&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;** 在 Linux 环境下，请用互斥锁和条件变量实现哲学家就餐的多线程应用程序。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;** 在 Linux 环境下，请建立一个多线程的模拟资源分配管理库，可通过银行家算法来避免死锁。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;../../../../../1-Theory/3-System/03-Operating-System/Internal-and-design-principle/35-Banker-algo-impl&quot; class=&quot;internal&quot; data-slug=&quot;1-Theory/3-System/03-Operating-System/Internal-and-design-principle/35-Banker-algo-impl&quot;&gt;35-Banker-algo-impl&lt;/a&gt;&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;** 扩展内核功能，实现读者优先的读写信号量。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;../../../../../1-Theory/3-System/03-Operating-System/Internal-and-design-principle/34-Reader-writer-impl&quot; class=&quot;internal&quot; data-slug=&quot;1-Theory/3-System/03-Operating-System/Internal-and-design-principle/34-Reader-writer-impl&quot;&gt;34-Reader-writer-impl&lt;/a&gt;&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;
&lt;p&gt;** 扩展内核功能，实现写者优先的读写信号量。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;*** 扩展内核功能，在内核中支持内核线程。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;*** 进一步扩展内核功能，在内核线程中支持同步互斥机制，实现内核线程用的 mutex, semaphore, cond-var。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;*** 扩展内核功能，实现多核支持下的同步互斥机制。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;*** 解决优先级反转问题：实现 RM 实时调度算法，设计优先级反转的实例，实现优先级天花板和优先级继承方法。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;问答题&quot;&gt;问答题&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#问答题&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;什么是并行？什么是并发？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;“并行” 指的是同时进行多个任务。在多 CPU 环境中，计算机具有多个独立的 CPU，可以同时执行多个任务。例如，如果你有两个 CPU，那么它们可以同时运行两个不同的程序，这样它们就是并行的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;“并发” 指的是多个任务的同时发生，但它们不一定是同时执行的。在单 CPU 环境中，并发和并行是通过 CPU 快速地在多个任务之间切换来模拟同时发生的效果。例如，如果你在同时运行多个程序，那么 CPU 可以快速地在这些程序之间切换，从而模拟它们同时发生的效果。这种情况下，这些程序是并发的，但不是并行的。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;单核和多核的并发处理&quot;&gt;单核和多核的并发处理&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#单核和多核的并发处理&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;为了创造临界区，单核处理器上可以【关中断】，多核处理器上需要使用【自旋锁】。请回答下列问题：&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;多核上可不可以只用【关中断】？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在多核处理器上仅使用关中断（disable interrupt）来实现临界区是不可行的，因为&lt;strong&gt;关中断只能保证当前核上的代码不会被中断，但不能保证其他核上的代码不会进入临界区&lt;/strong&gt;，对共享数据进行修改。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;单核上可不可以只用【自旋锁】？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单核处理器上可以使用自旋锁来实现临界区，但是并不是必须使用自旋锁，如上述的关中断。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;多核上的【自旋锁】是否需要同时【关中断】？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于多核处理器上的自旋锁，通常不需要关中断来创建临界区。相反，自旋锁的实现会使用处理器提供的硬件特性来确保原子性，例如原子操作、内存屏障等。这种方式能够避免全局中断，从而提高系统的性能。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[进阶] 假如某个锁不会在中断处理函数中被访问，是否还需要【关中断】？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在&lt;strong&gt;单核处理器上&lt;/strong&gt;，如果所有的代码都是在同一个上下文中运行，也就是没有中断或者线程切换的情况下，如果在代码中使用锁来保护共享资源，那么可以使用简单的互斥锁来实现临界区的保护，而不需要关中断。&lt;/li&gt;
&lt;li&gt;在&lt;strong&gt;多核处理器上&lt;/strong&gt;，不同的核心可以独立运行不同的线程，彼此之间不会互相干扰。在这种情况下，&lt;span class=&quot;text-highlight&quot;&gt;可以使用自旋锁等更高效的同步机制来实现临界区的保护&lt;/span&gt;。
&lt;ul&gt;
&lt;li&gt;如果&lt;span class=&quot;text-highlight&quot;&gt;代码中使用的锁需要在中断处理函数中被访问，那么在多核处理器上需要关中断来保护临界区&lt;/span&gt;。&lt;/li&gt;
&lt;li&gt;在中断处理函数中，由于上下文的切换，可能会发生竞争条件，因此需要通过关中断的方式来避免这种竞争。这样可以保证在中断处理函数执行期间，不会有其他线程在访问共享资源，从而保证临界区的安全性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;互斥锁和自旋锁的差异&quot;&gt;互斥锁和自旋锁的差异&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#互斥锁和自旋锁的差异&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;** Linux 的多线程应用程序使用的锁（例如 pthread_mutex_t）不是自旋锁，当上锁失败时会切换到其它进程执行。分析它和自旋锁的优劣，并说明为什么它不用自旋锁？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;互斥锁和自旋锁的优劣&lt;/strong&gt;：互斥锁和自旋锁的本质区别在于加锁失败时，是否会释放 CPU。互斥锁在加锁失败时，会释放 CPU，因此与自旋锁相比它的主要优势在于可以提高处理器的资源利用率，避免 CPU 空转的现象，但与之带来的是互斥锁的开销更大。这些开销主要包括两次线程上下文切换的成本：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;当线程加锁失败时，内核会把线程的状态从「运行」状态设置为「睡眠」状态，然后把 CPU 切换给其他线程运行；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;接着，当锁被释放时，之前「睡眠」状态的线程会变为「就绪」状态，然后内核会在合适的时间，把 CPU 切换给该线程运行。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;不使用自旋锁的原因是&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;可移植性：pthread_mutex_t 是 POSIX 标准中定义的一种互斥锁，不仅可以在 Linux 系统上使用，还可以在其他的 POSIX 兼容系统上使用，提高了应用程序的可移植性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;性能：自旋锁在多核处理器上可以提高并发性能，但是在单核处理器上可能会降低性能，因为自旋锁需要不断地检查锁的状态，如果锁一直处于被占用的状态，就会一直占用处理器时间。而pthread_mutex_t是一种阻塞锁，在锁被占用时，会将线程挂起，让出处理器时间，从而避免了空转浪费处理器资源的情况。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;死锁：使用自旋锁需要非常小心，否则容易出现死锁的情况。例如，当一个线程持有一个自旋锁并等待另一个自旋锁时，如果另一个线程持有了这个自旋锁并等待第一个自旋锁，就会出现死锁。而pthread_mutex_t是一种阻塞锁，在锁的等待队列中维护了线程的等待关系，可以避免死锁的情况。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;peterson-算法的-safety-和-liveness-性质&quot;&gt;Peterson 算法的 safety 和 liveness 性质&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#peterson-算法的-safety-和-liveness-性质&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;*** 程序在运行时具有两种性质：safety: something bad will never happen；liveness: something good will eventually occur. 分析并证明 Peterson 算法的 safety 和 liveness 性质。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面是这两个性质的证明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Safety性质：&lt;/p&gt;
&lt;p&gt;假设同时有两个线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;和&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;，它们都试图进入其临界区，即执行关键代码段。如果两个线程同时进入关键代码段，就会发生竞态条件，可能导致不正确的结果。因此，我们希望确保只有一个线程能够进入其临界区。&lt;/p&gt;
&lt;p&gt;Peterson算法确保了只有一个线程可以进入其临界区。这是因为，在进入临界区之前，线程必须首先尝试获取锁。如果另一个线程已经获得了锁，则当前线程将被阻塞，直到另一个线程释放锁。因此，只有一个线程可以进入其临界区，这证明了Peterson算法的safety性质。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Liveness性质：&lt;/p&gt;
&lt;p&gt;我们需要证明，如果一个线程尝试进入其临界区，则它最终将能够进入。假设线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;和&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;都试图进入其临界区。如果线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;先尝试进入其临界区，则线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;会被阻塞，直到线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;退出其临界区并释放锁。反之亦然。&lt;/p&gt;
&lt;p&gt;假设线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;试图进入其临界区，但是线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;已经占用了锁并且正在执行其临界区。线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;将被阻塞，并等待线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;释放锁。线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;将在其临界区内执行，并最终退出其临界区并释放锁。此时，线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;将获得锁，并能够进入其临界区。同样，如果线程&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3011em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;试图进入其临界区，那么也将发生类似的过程。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此，Peterson算法保证了线程能够最终进入其临界区，这证明了Peterson算法的liveness性质。&lt;/p&gt;
&lt;h4 id=&quot;信号量的数量之含义&quot;&gt;信号量的数量之含义&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#信号量的数量之含义&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;信号量结构中的整数分别为 + n、0、-n 的时候，各自代表什么状态或含义？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;+n：还有 n 个可用资源&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;0：所有可用资源恰好耗尽&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;-n：有n个进程申请了资源但无资源可用，被阻塞。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;pv-操作的原子性如何实现&quot;&gt;PV 操作的原子性如何实现？&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#pv-操作的原子性如何实现&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;** 考虑如下信号量实现代码：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;class Semaphore {
  int sem;
  WaitQueue q;
}
Semaphore::P() {
  sem --;
  if(sem &amp;#x3C; 0) {
    Add this thread to q.
    block.
  }
}
Semaphore::V() {
  sem ++;
  if(sem &amp;#x3C;= 0) {
    t = Remove a thread from q;
    wakeup(t);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;假如 P 操作或 V 操作不是原子操作，会出现什么问题？举一个例子说明。上述代码能否运行在用户态？上面代码的原子性是如何保证的？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果 P 操作或 V 操作不是原子操作，将无法实现资源的互斥访问。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P 操作和 V 操作都是通过关中断来实现的&lt;/strong&gt;（可以再确认一下这点）。&lt;/li&gt;
&lt;li&gt;上述代码不能运行在用户态，因为这将带给用户态程序使能/屏蔽中断这种特权，相当于相信应用并放权给它。这会面临和我们引入抢占式调度之前一样的问题：线程可以选择恶意永久关闭中断而独占所有 CPU 资源，这将会影响到整个系统的正常运行。&lt;/li&gt;
&lt;li&gt;因此，事实上至少&lt;span class=&quot;text-highlight&quot;&gt;在 RISC-V 这样含多个特权级的架构中，这甚至是完全做不到的&lt;/span&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;条件变量-wait-操作&quot;&gt;条件变量 wait 操作&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#条件变量-wait-操作&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;** 条件变量的 Wait 操作为什么必须关联一个锁？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当调用条件变量的 wait 操作阻塞当前线程的时候，该操作是在管程过程中，因此此时当前线程持有锁。&lt;span class=&quot;text-highlight&quot;&gt;在持有锁的情况下不能陷入阻塞 ，因此在陷入阻塞状态之前当前线程必须先释放锁；当被阻塞的线程被其他线程使用 signal 操作唤醒之后，需要重新获取到锁才能继续执行&lt;/span&gt;，不然的话就无法保证管程过程的互斥访问。&lt;/p&gt;
&lt;p&gt;因此，站在线程的视角，必须持有锁才能调用条件变量的 wait 操作阻塞自身。&lt;/p&gt;
&lt;ol start=&quot;8&quot;&gt;
&lt;li&gt;** 下面是条件变量的 wait 操作实现伪代码：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;Condvar::wait(lock) {
  Add this thread to q.
  lock.unlock();
  schedule();
  lock.lock();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果改成下面这样：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Condvar::wait() {
  Add this thread to q.
  schedule();
}
lock.unlock();
condvar.wait();
lock.lock();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;会出现什么问题？举一个例子说明。&lt;/p&gt;
&lt;p&gt;这种情况就是第7题提到的条件变量的wait操作没有关联一个锁。会造成被阻塞的线程被其他线程使用 signal 操作唤醒之后，无法获取锁，从而无法保证管程过程的互斥访问，导致管程失效。&lt;/p&gt;
&lt;ol start=&quot;9&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;死锁的必要条件是什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;三必要、一等待&lt;/p&gt;
&lt;h4 id=&quot;死锁预防如何实现&quot;&gt;死锁预防如何实现？&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#死锁预防如何实现&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;10&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;什么是死锁预防，举例并分析。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;预防死锁只需要破坏死锁的四个必要条件之一即可，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;破坏互斥条件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;破坏不可剥夺条件： 当进程的新资源不可取得时，释放自己已有的资源，待以后需要时重新申请。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;破坏请求并保持条件：进程在运行前一次申请完它所需要的全部资源，在它的资源为满足前，不把它投入运行。一旦投入运行，这些资源都归它所有，不能被剥夺。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;破坏循环等待条件：给锁/访问的资源进行排序，要求每个线程都按照排好的顺序依次申请锁和访问资源&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;银行家算法如何判断安全性&quot;&gt;银行家算法如何判断安全性？&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#银行家算法如何判断安全性&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;11&quot;&gt;
&lt;li&gt;** 描述银行家算法如何判断安全性。&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;设置两个向量:工作向量 Work，表示操作系统可提供给线程继续运行所需的各类资源数目，它含有 m 个元素，初始时，Work = Available；结束向量 Finish，表示系统是否有足够的资源分配给线程，使之运行完成。初始时 &lt;code&gt;Finish[0..n-1] = false&lt;/code&gt;，表示所有线程都没结束；当有足够资源分配给线程时，设置 &lt;code&gt;Finish[i] = true&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;从线程集合中找到一个能满足下述条件的线程&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Finish[i] == false;
Need[i,j] &amp;#x3C;= Work[j];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;若找到，执行步骤3，否则，执行步骤4。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当线程 &lt;code&gt;thr[i]&lt;/code&gt; 获得资源后，可顺利执行，直至完成，并释放出分配给它的资源，故应执行:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Work[j] = Work[j] + Allocation[i,j];
Finish[i] = true;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;跳转回步骤2&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果 &lt;code&gt;Finish[0..n-1]&lt;/code&gt; 都为 true，则表示系统处于安全状态；否则表示系统处于不安全状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通过操作系统调度，如银行家算法来避免死锁不是广泛使用的通用方案。因为从线程执行的一般情况上看，银行家算法需要提前获知线程总的资源申请量，以及未来的每一次请求，而这些请求对于一般线程而言在运行前是不可知或随机的。另外，即使在某些特殊情况下，可以提前知道线程的资源申请量等信息，多重循环的银行家算法开销也是很大的，不适合于对性能要求很高的操作系统中。&lt;/p&gt;
&lt;h2 id=&quot;实验练习&quot;&gt;实验练习&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#实验练习&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;实验练习包括实践作业和问答作业两部分。&lt;/p&gt;
&lt;h3 id=&quot;编程作业&quot;&gt;编程作业&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#编程作业&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;银行家算法分数更新&quot;&gt;银行家算法——分数更新&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#银行家算法分数更新&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;注解：本实验为用户态实验，请在 Linux 环境下完成。&lt;/p&gt;
&lt;p&gt;背景：在智能体大赛平台 &lt;a href=&quot;https://www.saiblo.net/&quot; class=&quot;external&quot;&gt;Saiblo&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; 网站上每打完一场双人天梯比赛后需要用 ELO 算法更新双方比分。由于 Saiblo 的评测机并发性很高，且 ELO 算法中的分值变动与双方变动前的分数有关，因此更新比分前时必须先为两位选手加锁。&lt;/p&gt;
&lt;p&gt;作业：请模拟一下上述分数更新过程，简便起见我们简化为有 p 位选手参赛（编号 &lt;code&gt;[0, p)&lt;/code&gt; 或 &lt;code&gt;[1, p]&lt;/code&gt;），初始分值为 1000 分，有 m 个评测机线程（生产者）给出随机的评测结果（两位不同选手的编号以及胜负结果，结果可能为平局），有 n 个 worker 线程（消费者）获取结果队列并更新数据库（全局变量等共享数据）记录的分数。m 个评测机各自模拟 k 场对局结果后结束线程，全部对局比分更新完成后主线程打印每位选手最终成绩以及所有选手分数之和。&lt;/p&gt;
&lt;p&gt;上述参数 p、m、n、k 均为可配置参数（命令行传参或程序启动时从 stdin 输入）。&lt;/p&gt;
&lt;p&gt;简便起见不使用 ELO 算法，简化更新规则为：若不为平局，当 胜者分数 &gt;= 败者分数 时胜者 +20，败者 -20，否则胜者 +30，败者 -30；若为平局，分高者 -10，分低者 + 10（若本就同分保持则不变）。&lt;/p&gt;
&lt;p&gt;消费者核心部分可参考如下伪码：&lt;/p&gt;
&lt;p&gt;获取选手 A 的锁 获取选手 B 的锁 更新 A、B 分数 睡眠 1ms（模拟数据库更新延时） 释放选手 B 的锁 释放选手 A 的锁&lt;/p&gt;
&lt;p&gt;tips:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;由于 ELO 以及本题中给出的简化更新算法均为零和算法，因此出现冲突后可以从所有选手分数之和明显看出来，正确处理时它应该永远为 1000p&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;将一个 worker 线程看作哲学家，将 worker 正在处理的一场对局的两位选手看作两根筷子，则得到了经典的哲学家就餐问题&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;实现-eventfd&quot;&gt;实现 eventfd&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#实现-eventfd&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 Linux 中有一种用于事件通知的文件描述符，称为 eventfd 。其核心是一个 64 位无符号整数的计数器，在非信号量模式下，若计数器值不为零，则 read 函数会从中读出计数值并将其清零，否则读取失败； write 函数将缓冲区中的数值加入到计数器中。在信号量模式下，若计数器值非零，则 read 操作将计数值减一，并返回 1 ； write 将计数值加一。我们将实现一个新的系统调用： sys_eventfd2 。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;eventfd&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;syscall ID: 290&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;功能：创建一个 eventfd， &lt;a href=&quot;https://linux.die.net/man/2/eventfd&quot; class=&quot;external&quot;&gt;eventfd 标准接口&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; 。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;C 接口： &lt;code&gt;int eventfd (unsigned int initval, int flags)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rust 接口： &lt;code&gt;fn eventfd (initval: u32, flags: i32) -&gt; i32&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;initval: 计数器的初值。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;flags: 可以设置为 0 或以下两个 flag 的任意组合（按位或）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;EFD_SEMAPHORE (1) ：设置该 flag 时，将以信号量模式创建 eventfd 。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;EFD_NONBLOCK (2048) ：若设置该 flag ，对 eventfd 读写失败时会返回 -2 ，否则将阻塞等待直至读或写操作可执行为止。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;通过 write 写入 eventfd 时，缓冲区大小必须为 8 字节。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;进程 fork 时，子进程会继承父进程创建的 eventfd ，且指向同一个计数器。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;返回值：如果出现了错误则返回 -1，否则返回创建成功的 eventfd 编号。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可能的错误&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;flag 不合法。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;创建的文件描述符数量超过进程限制&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;注解&lt;/p&gt;
&lt;p&gt;还有一个 sys_eventfd 系统调用（调用号 284），与 sys_eventfd2 的区别在于前者不支持传入 flags 。&lt;/p&gt;
&lt;p&gt;Linux 中的原生异步 IO 接口 libaio 就使用了 eventfd 作为内核完成 IO 操作之后通知应用程序的机制。&lt;/p&gt;
&lt;h4 id=&quot;实验要求&quot;&gt;实验要求&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#实验要求&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;完成分支: ch8-lab&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;实验目录要求不变。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过所有测例。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;实验练习的提交报告要求&quot;&gt;实验练习的提交报告要求&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#实验练习的提交报告要求&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;简单总结本次实验与上个实验相比你增加的东西。（控制在 5 行以内，不要贴代码）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;完成问答问题&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(optional) 你对本次实验设计及难度的看法。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt; ]]></description>
    <pubDate>Sun, 12 Apr 2026 18:00:21 GMT</pubDate>
  </item><item>
    <title>9-设备IO</title>
    <link>https://senjlearning.space/1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/9-%E8%AE%BE%E5%A4%87IO</link>
    <guid>https://senjlearning.space/1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/9-%E8%AE%BE%E5%A4%87IO</guid>
    <description><![CDATA[ &lt;h2 id=&quot;课后练习&quot;&gt;课后练习&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#课后练习&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;编程题&quot;&gt;编程题&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#编程题&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;*** 在 Linux 的字符（命令行）模式下，编写贪吃蛇小游戏应用程序。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;问答题&quot;&gt;问答题&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#问答题&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;字符设备的特点是什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;字符（char）设备是个能够像字节流（类似文件）一样被访问的设备，由字符设备驱动程序来实现这种特性。字符设备驱动程序通常至少要实现 open、close、read 和 write 的系统调用。&lt;/p&gt;
&lt;p&gt;字符终端（/dev/console）和串口（/dev/ttyS0以及类似设备）就是两个字符设备，它们能很好的说明“流”这种抽象概念。&lt;/p&gt;
&lt;p&gt;字符设备可以通过文件节点来访问，比如/dev/tty1和/dev/lp0等。这些设备文件和普通文件之间的唯一差别在于对普通文件的访问可以前后移动访问位置，而大多数字符设备是一个只能顺序访问的数据通道。然而，也存在具有数据区特性的字符设备，访问它们时可前后移动访问位置。例如framebuffer就是这样的一个设备，app可以用mmap或lseek访问抓取的整个图像。&lt;/p&gt;
&lt;p&gt;在/dev下执行ls -l ,可以看到很多创建好的设备节点：&lt;/p&gt;
&lt;p&gt;字符设备文件（类型为c），设备文件是没有文件大小的，取而代之的是两个号码：主设备号5 +次设备号1 。&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;块设备的特点是什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;和字符设备类似，块设备也是通过/dev 目录下的文件系统节点来访问。块设备（例如磁盘）上能够容纳 filesystem。在大多数的 Unix 系统中，进行 I/O 操作时块设备每次只能传输一个或多个完整的块，而每块包含 512 字节（或 2 的更高次幂字节的数据）。&lt;/p&gt;
&lt;p&gt;Linux 可以让 app 像字符设备一样地读写块设备，允许一次传递任意多字节的数据。因此，块设备和字符设备的区别仅仅在于内核内部管理数据的方式，也就是内核及驱动程序之间的软件接口，而这些不同对用户来讲是透明的。在内核中，和字符驱动程序相比，块驱动程序具有完全不同的接口。&lt;/p&gt;
&lt;p&gt;块设备文件（类型为 b）：&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;网络设备的特点是什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;任何网络事物都需要经过一个网络接口形成，网络接口是一个能够和其他主机交换数据的设备。接口通常是一个硬件设备，但也可能是个纯软件设备，比如回环（loopback）接口。&lt;/p&gt;
&lt;p&gt;网络接口由内核中的网络子系统驱动，负责发送和接收数据包。许多网络连接（尤其是使用 TCP 协议的连接）是面向流的，但网络设备却围绕数据包的传送和接收而设计。网络驱动程序不需要知道各个连接的相关信息，它只要处理数据包即可。&lt;/p&gt;
&lt;p&gt;由于不是面向流的设备，因此将网络接口映射到 filesystem 中的节点（比如/dev/tty1）比较困难。&lt;/p&gt;
&lt;p&gt;Unix 访问网络接口的方法仍然是给它们分配一个唯一的名字（​
​比如 eth0​
​），但这个名字在 filesystem 中不存在对应的节点。内核和网络设备驱动程序间的通信，完全不同于内核和字符以及块驱动程序之间的通信，内核调用一套和数据包相关的函数 socket，也叫套接字。&lt;/p&gt;
&lt;p&gt;查看网络设备使用命令 ifconfig：
&lt;img src=&quot;../../../../../1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/assets/9-设备IO-ifconfig.png&quot; width=&quot;auto&quot; height=&quot;auto&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;五种-io-模型&quot;&gt;五种 I/O 模型&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#五种-io-模型&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;阻塞 I/O、非阻塞 I/O、多路复用 I/O、信号驱动 I/O、异步 I/O 这几种 I/O 方式的特点和区别是？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;../../../../../1-Theory/3-System/03-Operating-System/rCore-tutorial/9-IO-devices-management/10-IO-devices#io-执行模型&quot; class=&quot;internal alias&quot; data-slug=&quot;1-Theory/3-System/03-Operating-System/rCore-tutorial/9-IO-devices-management/10-IO-devices&quot;&gt;O 执行模型&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;io-的三种传输方式&quot;&gt;I/O 的三种传输方式&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#io-的三种传输方式&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;IO 数据传输有哪几种？各自的特征是什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;../../../../../1-Theory/3-System/03-Operating-System/rCore-tutorial/9-IO-devices-management/10-IO-devices#io-传输方式&quot; class=&quot;internal alias&quot; data-slug=&quot;1-Theory/3-System/03-Operating-System/rCore-tutorial/9-IO-devices-management/10-IO-devices&quot;&gt;O 传输方式&lt;/a&gt;&lt;/p&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;描述磁盘 I/O 操作时间组成。其中的瓶颈是哪部分？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(I/O 排队延迟、) 寻道时间、旋转延迟、数据传输时间 (、RPS 失败时间)&lt;/p&gt;
&lt;h4 id=&quot;risc-v-异常中断详细&quot;&gt;RISC-V 异常、中断详细&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#risc-v-异常中断详细&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;** RISC-V 中的异常，中断的区别是啥？有几类中断？每类中断有哪些具体的常见中断实例？PLIC/CLINT 的具体功能是啥？中断可否从 M 态响应委托给 S 态响应？S 态响应可否委托给 U 态响应？与中断相关的 M 态 / S 态寄存器有哪些，这些寄存器的功能是啥？外设产生一个中断后，PLIC/CPU/OS 如何协同进行响应处理的？
&lt;a href=&quot;../../../../../1-Theory/3-System/02-Architecture/RISC-V/A1-RISC-V异常、中断&quot; class=&quot;internal alias&quot; data-slug=&quot;1-Theory/3-System/02-Architecture/RISC-V/A1-RISC-V异常、中断&quot;&gt;A1-RISC-V异常、中断&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;io-控制命令如何通过系统调用实现&quot;&gt;IO 控制命令如何通过系统调用实现？&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#io-控制命令如何通过系统调用实现&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol start=&quot;8&quot;&gt;
&lt;li&gt;
&lt;p&gt;** 是否可以把设备抽象为文件？如果可以，那用户进程对设备发出 IO 控制命令，如何通过系统调用实现？
设备当然可以抽象为的文件，操作系统对文件提供统一的接口，方便上层用户使用。通常接口有 open, read, write, exec, close 等&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;** GPU 是外设吗？GPU 与 CPU 交互和数据传输的方式是什么？（需要查看一下相关 GPU 工作过程的信息）&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;../../../../../1-Theory/3-System/03-Operating-System/rCore-tutorial/9-IO-devices-management/60-VirtIO_GPU-drivers#virtio-gpu-设备的-io-操作&quot; class=&quot;internal alias&quot; data-slug=&quot;1-Theory/3-System/03-Operating-System/rCore-tutorial/9-IO-devices-management/60-VirtIO_GPU-drivers&quot;&gt;O 操作&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;实验练习&quot;&gt;实验练习&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#实验练习&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;实验练习包括实践作业和问答作业两部分。本次难度： &lt;strong&gt;中&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;实践作业&quot;&gt;实践作业&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#实践作业&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;支持图形显示的应用&quot;&gt;支持图形显示的应用&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#支持图形显示的应用&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;本章虽然讲述了 virtio-gpu 设备驱动，且可以直接进行图形显示，但这个设备驱动并没有加入到操作系统中，使得应用程序无法进行图形显示。lab8 的练习要求操作系统支持有彩色图形显示的应用，使得我们可以从单调的字符交互界跳入到多彩的图形界面中。&lt;/p&gt;
&lt;h4 id=&quot;实验要求&quot;&gt;实验要求&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#实验要求&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;实现分支：ch9-lab&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;实验目录要求不变&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在裸机上让操作系统支持 “贪吃蛇” 游戏应用&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;需要在操作系统中加入 virtio-gpu 设备驱动程序；需要实现设备文件 &lt;code&gt;/dev/fb0&lt;/code&gt; 和相关操作，用于应用访问显存。&lt;/p&gt;
&lt;p&gt;可以正确执行 “贪吃蛇” 游戏应用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;问答作业&quot;&gt;问答作业&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#问答作业&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;通过阅读和运行试验等分析，你认为在目前的操作系统中，如果运行在用户态，可以响应哪些中断？如果运行在内核态，可以响应哪些中断？请简要描述分析经过。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于串口驱动程序，在 RustSBI 中有具体的实现，请问它与本章讲的串口驱动有何异同之处？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于目前操作系统中的 &lt;code&gt;virtio-blk&lt;/code&gt; 设备驱动程序，存在哪些可以改进的地方来提升性能？&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;实验练习的提交报告要求&quot;&gt;实验练习的提交报告要求&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#实验练习的提交报告要求&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;简单总结本次实验你编程的内容。（控制在 5 行以内，不要贴代码）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;完成问答问题。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(optional) 你对本次实验设计及难度 / 工作量的看法，以及有哪些需要改进的地方，欢迎畅所欲言。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt; ]]></description>
    <pubDate>Sun, 12 Apr 2026 18:00:21 GMT</pubDate>
  </item><item>
    <title>92-Linux-softirq</title>
    <link>https://senjlearning.space/1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/92-Linux-softirq</link>
    <guid>https://senjlearning.space/1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/92-Linux-softirq</guid>
    <description><![CDATA[ &lt;h2 id=&quot;softirqs&quot;&gt;Softirqs&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#softirqs&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;softirqs can not be used by device drivers, they are reserved for various kernel subsystems. Because of this there is a fixed number of softirqs defined at compile time. For the current kernel version we have the following types defined:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;enum {
    HI_SOFTIRQ = 0,
    TIMER_SOFTIRQ,
    NET_TX_SOFTIRQ,
    NET_RX_SOFTIRQ,
    BLOCK_SOFTIRQ,
    IRQ_POLL_SOFTIRQ,
    TASKLET_SOFTIRQ,
    SCHED_SOFTIRQ,
    HRTIMER_SOFTIRQ,
    RCU_SOFTIRQ,
    NR_SOFTIRQS
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each type has a specific purpose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;HI_SOFTIRQ&lt;/em&gt; and &lt;em&gt;TASKLET_SOFTIRQ&lt;/em&gt; - running tasklets&lt;/li&gt;
&lt;li&gt;&lt;em&gt;TIMER_SOFTIRQ&lt;/em&gt; - running timers&lt;/li&gt;
&lt;li&gt;&lt;em&gt;NET_TX_SOFIRQ&lt;/em&gt; and &lt;em&gt;NET_RX_SOFTIRQ&lt;/em&gt; - used by the networking subsystem&lt;/li&gt;
&lt;li&gt;&lt;em&gt;BLOCK_SOFTIRQ&lt;/em&gt; - used by the IO subsystem&lt;/li&gt;
&lt;li&gt;&lt;em&gt;BLOCK_IOPOLL_SOFTIRQ&lt;/em&gt; - used by the IO subsystem to increase performance when the iopoll handler is invoked;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;SCHED_SOFTIRQ&lt;/em&gt; - load balancing&lt;/li&gt;
&lt;li&gt;&lt;em&gt;HRTIMER_SOFTIRQ&lt;/em&gt; - implementation of high precision timers&lt;/li&gt;
&lt;li&gt;&lt;em&gt;RCU_SOFTIRQ&lt;/em&gt; - implementation of RCU type mechanisms&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The highest priority is the &lt;em&gt;HI_SOFTIRQ&lt;/em&gt; type softirqs, followed in order by the other softirqs defined. &lt;em&gt;RCU_SOFTIRQ&lt;/em&gt; has the lowest priority.&lt;/p&gt;
&lt;p&gt;Softirqs are running in interrupt context which means that they can not call blocking functions. If the sofitrq handler requires calls to such functions, work queues can be scheduled to execute these blocking calls.&lt;/p&gt;
&lt;h3 id=&quot;tasklets&quot;&gt;Tasklets&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#tasklets&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A tasklet is a special form of deferred work that runs in interrupt context, just like softirqs. The main difference between sofirqs and tasklets is that tasklets can be allocated dynamically and thus they can be used by device drivers. A tasklet is represented by &lt;code&gt;struct tasklet&lt;/code&gt; and as many other kernel structures it needs to be initialized before being used. A pre-initialized tasklet can defined as following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void handler(unsigned long data);

DECLARE_TASKLET(tasklet, handler, data);
DECLARE_TASKLET_DISABLED(tasklet, handler, data);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we want to initialize the tasklet manually we can use the following approach:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void handler(unsigned long data);

struct tasklet_struct tasklet;

tasklet_init(&amp;#x26;tasklet, handler, data);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;em&gt;data&lt;/em&gt; parameter will be sent to the handler when it is executed.&lt;/p&gt;
&lt;p&gt;Programming tasklets for running is called scheduling. Tasklets are running from softirqs. Tasklets scheduling is done with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void tasklet_schedule(struct tasklet_struct *tasklet);

void tasklet_hi_schedule(struct tasklet_struct *tasklet);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When using &lt;em&gt;tasklet_schedule&lt;/em&gt;, a &lt;em&gt;TASKLET_SOFTIRQ&lt;/em&gt; softirq is scheduled and all tasklets scheduled are run. For &lt;em&gt;tasklet_hi_schedule&lt;/em&gt;, a &lt;em&gt;HI_SOFTIRQ&lt;/em&gt; softirq is scheduled.&lt;/p&gt;
&lt;p&gt;If a tasklet was scheduled multiple times and it did not run between schedules, it will run once. Once the tasklet has run, it can be re-scheduled, and will run again at a later timer. Tasklets can be re-scheduled from their handlers.&lt;/p&gt;
&lt;p&gt;Tasklets can be masked and the following functions can be used:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void tasklet_enable(struct tasklet_struct * tasklet );
void tasklet_disable(struct tasklet_struct * tasklet );
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember that since tasklets are running from softirqs, blocking calls can not be used in the handler function.&lt;/p&gt;
&lt;h3 id=&quot;timers&quot;&gt;Timers&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#timers&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A particular type of deferred work, very often used, are timers. They are defined by &lt;code&gt;struct timer_list&lt;/code&gt;. They run in interrupt context and are implemented on top of softirqs.&lt;/p&gt;
&lt;p&gt;To be used, a timer must first be initialized by calling &lt;code&gt;timer_setup()&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;#x3C;linux / sched.h&gt;

void timer_setup(struct timer_list * timer,
                 void (*function)(struct timer_list *),
                 unsigned int flags);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above function initializes the internal fields of the structure and associates &lt;em&gt;function&lt;/em&gt; as the timer handler. Since timers are planned over softirqs, blocking calls can not be used in the code associated with the treatment function.&lt;/p&gt;
&lt;p&gt;Scheduling a timer is done with &lt;code&gt;mod_timer()&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int mod_timer(struct timer_list *timer, unsigned long expires);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where &lt;em&gt;expires&lt;/em&gt; is the time (in the future) to run the handler function. The function can be used to schedule or reschedule a timer.&lt;/p&gt;
&lt;p&gt;The time unit timers is &lt;em&gt;jiffie&lt;/em&gt;. The absolute value of a jiffie is dependent on the platform and it can be found using the &lt;code&gt;HZ&lt;/code&gt; macro that defines the number of jiffies for 1 second. To convert between jiffies (&lt;em&gt;jiffies_value&lt;/em&gt;) and seconds (&lt;em&gt;seconds_value&lt;/em&gt;), the following formulas are used:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jiffies_value = seconds_value * HZ ;
seconds_value = jiffies_value / HZ ;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The kernel mantains a counter that contains the number of jiffies since the last boot, which can be accessed via the &lt;code&gt;jiffies&lt;/code&gt; global variable or macro. We can use it to calculate a time in the future for timers:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;#x3C;linux/jiffies.h&gt;

unsigned long current_jiffies, next_jiffies;
unsigned long seconds = 1;

current_jiffies = jiffies;
next_jiffies = jiffies + seconds * HZ;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To stop a timer, use &lt;code&gt;del_timer()&lt;/code&gt; and &lt;code&gt;del_timer_sync()&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int del_timer(struct timer_list *timer);
int del_timer_sync(struct timer_list *timer);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thse functions can be called for both a scheduled timer and an unplanned timer. &lt;code&gt;del_timer_sync()&lt;/code&gt; is used to eliminate the races that can occur on multiprocessor systems, since at the end of the call it is guaranteed that the timer processing function does not run on any processor.&lt;/p&gt;
&lt;p&gt;A frequent mistake in using timers is that we forget to turn off timers. For example, before removing a module, we must stop the timers because if a timer expires after the module is removed, the handler function will no longer be loaded into the kernel and a kernel oops will be generated.&lt;/p&gt;
&lt;p&gt;The usual sequence used to initialize and schedule a one second timeout is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;#x3C;linux/sched.h&gt;

void timer_function(struct timer_list *);

struct timer_list timer ;
unsigned long seconds = 1;

timer_setup(&amp;#x26;timer, timer_function, 0);
mod_timer(&amp;#x26;timer, jiffies + seconds * HZ);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And to stop it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;del_timer_sync(&amp;#x26;timer);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;locking&quot;&gt;Locking&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#locking&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For synchronization between code running in process context (A) and code running in softirq context (B) we need to use special locking primitives. We must use spinlock operations augmented with deactivation of bottom-half handlers on the current processor in (A), and in (B) only basic spinlock operations. Using spinlocks makes sure that we don’t have races between multiple CPUs while deactivating the softirqs makes sure that we don’t deadlock in the softirq is scheduled on the same CPU where we already acquired a spinlock.&lt;/p&gt;
&lt;p&gt;We can use the &lt;code&gt;local_bh_disable()&lt;/code&gt; and &lt;code&gt;local_bh_enable()&lt;/code&gt; to disable and enable softirqs handlers (and since they run on top of softirqs also timers and tasklets):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void local_bh_disable(void);
void local_bh_enable(void);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nested calls are allowed, the actual reactivation of the softirqs is done only when all local_bh_disable() calls have been complemented by local_bh_enable() calls:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* We assume that softirqs are enabled */
local_bh_disable();  /* Softirqs are now disabled */
local_bh_disable();  /* Softirqs remain disabled */

local_bh_enable();  /* Softirqs remain disabled */
local_bh_enable();  /* Softirqs are now enabled */
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote class=&quot;callout warning&quot; data-callout=&quot;warning&quot;&gt;
&lt;div class=&quot;callout-title&quot;&gt;
                  &lt;div class=&quot;callout-icon&quot;&gt;&lt;/div&gt;
                  &lt;div class=&quot;callout-title-inner&quot;&gt;&lt;p&gt;Attention&lt;/p&gt;&lt;/div&gt;
                  
                &lt;/div&gt;
&lt;div class=&quot;callout-content&quot;&gt;
&lt;p&gt;These above calls will disable the softirqs only on the local processor and they are usually not safe to use, they must be complemented with spinlocks.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Most of the time device drivers will use special versions of spinlocks calls for synchronization like &lt;code&gt;spin_lock_bh()&lt;/code&gt; and &lt;code&gt;spin_unlock_bh()&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void spin_lock_bh(spinlock_t *lock);
void spin_unlock_bh(spinlock_t *lock);
&lt;/code&gt;&lt;/pre&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#footnote-label&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://linux-kernel-labs.github.io/refs/pull/189/merge/labs/deferred_work.html#id2&quot; class=&quot;external&quot;&gt;Deferred work — The Linux Kernel documentation&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt; ]]></description>
    <pubDate>Sun, 12 Apr 2026 18:00:21 GMT</pubDate>
  </item><item>
    <title>0-操作系统概述</title>
    <link>https://senjlearning.space/1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/0-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%A6%82%E8%BF%B0</link>
    <guid>https://senjlearning.space/1-Theory/3-System/03-Operating-System/rCore-tutorial/Practice/0-%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%A6%82%E8%BF%B0</guid>
    <description><![CDATA[ &lt;h2 id=&quot;课后练习&quot;&gt;课后练习&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#课后练习&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;课后练习和实验练习中的题目难度表示：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;容易&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;** 有一定工作量&lt;/li&gt;
&lt;li&gt;*** 有难度&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;编程题&quot;&gt;编程题&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#编程题&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;在你日常使用的操作系统环境中安装并配置好实验环境。简要说明你碰到的问题 / 困难和解决方法。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;在 Linux 环境下编写一个会产生异常的应用程序，并简要解释操作系统的处理结果。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;例如，对于这样一段 C 程序，其中包含一个除以零的操作：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;#x3C;stdio.h&gt;

int main() {
    printf(&quot;1 / 0 = %d&quot;, 1 / 0);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在基于 x86-64 Linux 的环境下编译运行结果如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gcc divzero
$ ./divzero
Floating point exception (core dumped)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;程序接收到了一个“浮点数异常”而异常终止。使用 &lt;code&gt;strace&lt;/code&gt; 可以看到更详细的信号信息：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ strace ./divzero
[... 此处省略系统调用跟踪输出]
--- SIGFPE {si_signo=SIGFPE, si_code=FPE_INTDIV, si_addr=0x401131} ---
+++ killed by SIGFPE (core dumped) +++
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用 gdb 的 &lt;code&gt;disassemble&lt;/code&gt; 命令可以看到发生异常的指令&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gdb divzero
Reading symbols from divzero...
(gdb) r
Starting program: [...]/divzero

Program received signal SIGFPE, Arithmetic exception.
0x0000000000401131 in main ()
(gdb) disassemble
Dump of assembler code for function main:
   0x0000000000401122 &amp;#x3C;+0&gt;:     push   %rbp
   0x0000000000401123 &amp;#x3C;+1&gt;:     mov    %rsp,%rbp
   0x0000000000401126 &amp;#x3C;+4&gt;:     mov    $0x1,%eax
   0x000000000040112b &amp;#x3C;+9&gt;:     mov    $0x0,%ecx
   0x0000000000401130 &amp;#x3C;+14&gt;:    cltd
=&gt; 0x0000000000401131 &amp;#x3C;+15&gt;:    idiv   %ecx
   0x0000000000401133 &amp;#x3C;+17&gt;:    mov    %eax,%esi
   0x0000000000401135 &amp;#x3C;+19&gt;:    mov    $0x402004,%edi
   0x000000000040113a &amp;#x3C;+24&gt;:    mov    $0x0,%eax
   0x000000000040113f &amp;#x3C;+29&gt;:    call   0x401030 &amp;#x3C;printf@plt&gt;
   0x0000000000401144 &amp;#x3C;+34&gt;:    mov    $0x0,%eax
   0x0000000000401149 &amp;#x3C;+39&gt;:    pop    %rbp
   0x000000000040114a &amp;#x3C;+40&gt;:    ret
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看出，应用程序在执行 idiv 指令（有符号除法指令）时发生了除以零异常，跳转至操作系统处理。操作系统把它转换为一个信号 SIGFPE，使用信号处理机制处理这个异常。该程序收到 SIGFPE 时应发生的行为是异常终止，于是操作系统将其终止，并将异常退出的信息报告给 shell 进程。&lt;/p&gt;
&lt;p&gt;需要注意的是，异常的处理和与信号的对应是与架构相关的。例如，RISC-V 架构下除以零不是异常，而是有个确定的结果。此外，&lt;span class=&quot;text-highlight&quot;&gt;不同架构下具体异常和信号的对应关系也是不同的&lt;/span&gt;，甚至有些混乱（例如，这里明明是整数除以零错误，却报告了“浮点数”异常）。&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;** 在 Linux 环境下编写一个可以睡眠 5 秒后打印出一个字符串，并把字符串内容存入一个文件中的应用程序 A。(基于 C 或 Rust 语言)&lt;/li&gt;
&lt;/ol&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;--shiki-light:#657B83;--shiki-dark:#abb2bf;--shiki-light-bg:#FDF6E3;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot; data-theme=&quot;solarized-light one-dark-pro&quot;&gt;&lt;code data-language=&quot;shell&quot; data-theme=&quot;solarized-light one-dark-pro&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;❯&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; cargo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; codequiz_3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;    Created&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; binary&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt; (application) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;codequiz_3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt; package&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;❯&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; cd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; codequiz_3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;❯&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; vim&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; src/main.rs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;❯&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; cargo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;  Compiling&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; codequiz_3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; v0.1.0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt; (/home/senjl/MyLearning/computer_science/operating_system/thu-rcore-2023  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;/practice/0-OS-overview/codequiz_3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;)  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;   Finished&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; dev&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt; [unoptimized &lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; debuginfo]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; target&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 0.48s&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;    Running&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;target/debug/codequiz_3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;Hello,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; rCore!&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;字符串已写入文件&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; output.txt&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 中。&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;❯&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; tree&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; .&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#56B6C2&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; Cargo.lock&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; Cargo.toml&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; output.txt&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; src&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;│   └──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; main.rs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;└──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; target&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; CACHEDIR.TAG&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;   └──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; debug&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;       ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; build&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;       ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; codequiz_3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;       ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; codequiz_3.d&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;       ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; deps&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;       │   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; codequiz_3-a812f2dab40f5ac3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;       │   └──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; codequiz_3-a812f2dab40f5ac3.d&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;       ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; examples&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;       └──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; incremental&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;           └──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; codequiz_3-2sso7tvhe66uy&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;               ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; s-got0uhkt85-10oknx4.lock&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;               └──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; s-got0uhkt85-10oknx4-uo39hi7ufjn3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 106ugw828sc9mjlo.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 16g4m2yq5qn83zb8.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 1jtth1d97viticks.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 1msngkgqmkyp2hqv.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 1vlxnagfwutl73pd.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 2a8ir0y65ll82o7f.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 2jdh0nk9fsqkq2e.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 2oazud4oz8bj2fgl.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 2v8pxbxipx6onl8k.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 3gczdpwh246wmvyr.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 3tnkveyfdmc7zza2.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 3ywfsf8o5iwo948a.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 49ypht22pb7yeaax.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 4fz4gs01qepy9b37.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 4g1u4m2p2cj8qm7v.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 4h8tss5f48uh2ip4.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 4o2kxft0an4w1ep5.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 4tn6tc3bcsk1pign.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; 4v6eho9bfsu5lhna.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; dep-graph.bin&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; gam1jc4fs45mii1.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; j922u05sg5spprr.o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   ├──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; query-cache.bin&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;                   └──&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; work-products.bin&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; directories,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D33682;--shiki-dark:#D19A66&quot;&gt; 34&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; files&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;❯&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; cat&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; output.txt&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;Hello,&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; rCore!%&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre style=&quot;--shiki-light:#657B83;--shiki-dark:#abb2bf;--shiki-light-bg:#FDF6E3;--shiki-dark-bg:#282c34&quot; tabindex=&quot;0&quot; data-language=&quot;rust&quot; data-theme=&quot;solarized-light one-dark-pro&quot;&gt;&lt;code data-language=&quot;rust&quot; data-theme=&quot;solarized-light one-dark-pro&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt;fs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt;File&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt;io&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt;Write&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt;thread&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;sleep;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt;Duration&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#93A1A1;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;    // 等待 5 秒&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#586E75;--shiki-light-font-weight:bold;--shiki-dark:#C678DD;--shiki-dark-font-weight:inherit&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt; sleep_duration&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt; Duration&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;from_secs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D33682;--shiki-dark:#D19A66&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;    sleep&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;sleep_duration&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#93A1A1;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;    // 要打印的字符串&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#586E75;--shiki-light-font-weight:bold;--shiki-dark:#C678DD;--shiki-dark-font-weight:inherit&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt; message&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; &quot;Hello, rCore!&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#93A1A1;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;    // 打印字符串到终端&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;    println!&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#93A1A1;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic&quot;&gt;    // 将字符串写入文件&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#586E75;--shiki-light-font-weight:bold;--shiki-dark:#C678DD;--shiki-dark-font-weight:inherit&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt; filename&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#56B6C2&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt; &quot;output.txt&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;--shiki-light:#586E75;--shiki-light-font-weight:bold;--shiki-dark:#C678DD;--shiki-dark-font-weight:inherit&quot;&gt; let&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt; Ok&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#586E75;--shiki-light-font-weight:bold;--shiki-dark:#C678DD;--shiki-dark-font-weight:inherit&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt; file&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt; File&lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#ABB2BF&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;create&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;filename&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;--shiki-light:#586E75;--shiki-light-font-weight:bold;--shiki-dark:#C678DD;--shiki-dark-font-weight:inherit&quot;&gt; let&lt;/span&gt;&lt;span style=&quot;--shiki-light:#CB4B16;--shiki-dark:#E5C07B&quot;&gt; Err&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#56B6C2&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt; write!&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;file&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;            eprintln!&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;&quot;写入文件时出错：{}&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;            println!&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;&quot;字符串已写入文件 {} 中。&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;filename&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;--shiki-light:#859900;--shiki-dark:#C678DD&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#61AFEF&quot;&gt;        eprintln!&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#2AA198;--shiki-dark:#98C379&quot;&gt;&quot;创建文件 {} 时出错。&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#268BD2;--shiki-dark:#E06C75&quot;&gt;filename&lt;/span&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#657B83;--shiki-dark:#ABB2BF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;*** 在 Linux 环境下编写一个应用程序 B，简要说明此程序能够体现操作系统的并发性、异步性、共享性和持久性。(基于 C 或 Rust 语言)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;注： 在类 Linux 环境下编写尝试用 GDB 等调试工具调试应用程序 A，能够设置断点，单步执行，显示变量信息。&lt;/p&gt;
&lt;h3 id=&quot;问答题&quot;&gt;问答题&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#问答题&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;什么是操作系统？操作系统的主要目标是什么？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;面向服务器的操作系统与面向手机的操作系统在功能上有何异同？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;对于目前的手机或桌面操作系统而言，操作系统是否应该包括网络浏览器？请说明理由。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;text-highlight&quot;&gt;操作系统的核心抽象有哪些？它们应对的对象是啥&lt;/span&gt;？&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;进程/线程 – CPU 时间&lt;/li&gt;
&lt;li&gt;地址空间 – 内存&lt;/li&gt;
&lt;li&gt;执行环境 – CPU 上复杂的环境（有中断异常等），和操作系统提供的功能（如系统调用）&lt;/li&gt;
&lt;li&gt;文件和文件描述符 – 存储和输入输出设备&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;操作系统与应用程序之间通过什么来进行互操作和数据交换？&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;互操作的方式：
&lt;ul&gt;
&lt;li&gt;应用程序调用系统调用主动让操作系统进行操作&lt;/li&gt;
&lt;li&gt;操作系统在中断异常发生时强制暂停应用程序进行相关操作&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;数据交换的方式：
&lt;ul&gt;
&lt;li&gt;系统调用时根据 ABI 规定在（比如）寄存器中传递参数&lt;/li&gt;
&lt;li&gt;复制数据：在内核占用的空间和用户占用的空间之间互相复制数据，如读写文件的时候从应用程序给出的缓冲区复制写的数据，或者复制读的数据到缓冲区&lt;/li&gt;
&lt;li&gt;（共享内存空间：如 io_uring）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;text-highlight&quot;&gt;操作系统的特征是什么&lt;/span&gt;？请结合你日常使用的操作系统的具体运行情况来进一步说明操作系统的特征。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以在普通的桌面机上运行基于 Linux 的平台上做操作系统实验时可能发生的事情为例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;虚拟性：如果物理内存相对不足，Linux 的 swap 机制会将不常用的内存内容转存到硬盘上，优先保证活跃的进程可以高速访问物理内存。&lt;/li&gt;
&lt;li&gt;并发性：正在运行的程序数量（包括并发运行的 gcc 或 rustc，和其它程序）可以超过 CPU 核心数，由操作系统来调度分配使用 CPU 时间。&lt;/li&gt;
&lt;li&gt;异步性：并行运行的编译器太多，可能会影响写代码用的文本编辑器性能，因为操作系统安排了更多时间运行编译器而不是文本编辑器进程。&lt;/li&gt;
&lt;li&gt;共享性：写代码和编译可以共享同一个文件系统，在同一块硬盘上读写，操作系统的文件系统相关模块（VFS）会调用文件系统实现和硬盘驱动安排这些读写操作。&lt;/li&gt;
&lt;li&gt;持久性：操作系统实验用的文件保存在文件系统中，晚上宿舍断电关机，明天早上起来可以从昨天保存的文件的状态继续工作。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;请说明基于 C 语言应用的执行环境与基于 Java 语言应用的执行环境的异同。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;** 请简要列举操作系统的系统调用的作用，以及简要说明与程序执行、内存分配、文件读写相关的 Linux 系统调用的大致接口和含义。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;系统调用的作用：
&lt;ul&gt;
&lt;li&gt;将操作系统实现和用户程序调用方式分开，作为一个抽象层方便开发和使用&lt;/li&gt;
&lt;li&gt;在让用户程序没法直接访问别的用户程序的地址空间和操作系统地址空间的情况下，作为一个统一的应用程序请求操作系统服务的入口，方便安全检查和审计。&lt;/li&gt;
&lt;li&gt;让用户程序能有限访问其不能直接访问的计算机资源和操作系统对象&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;在 Linux 中：
&lt;ul&gt;
&lt;li&gt;clone &lt;code&gt;（曾用的有 &lt;/code&gt; fork）创建进程；execve 传入文件路径、命令行参数、环境变量，加载新的程序替换当前进程。&lt;/li&gt;
&lt;li&gt;brk 修改或获取当前的堆顶的位置，增加堆顶地址分配空间，减小堆底地址释放空间；mmap 用于映射地址空间，也可以分配物理内存（MAP_ANONYMOUS），munmap 释放对应的地址空间和对应的内存。&lt;/li&gt;
&lt;li&gt;文件读写相关有 openat &lt;code&gt;（曾用的有 &lt;/code&gt; open）打开文件，read 读文件，write 写文件等。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;** 以你编写的可以睡眠 5 秒后打印出一个字符串的应用程序 A 为例，说明什么是控制流？什么是异常控制流？什么是进程、地址空间和文件？并简要描述操作系统是如何支持这个应用程序完成其工作并结束的。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;应用程序 A 中体现的操作系统相关概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;控制流&lt;/strong&gt;： &lt;code&gt;main&lt;/code&gt; 函数内一行一行往下执行，是一个顺序控制流；其中调用的标准库函数，是函数调用的控制流。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异常控制流&lt;/strong&gt;： 在 &lt;code&gt;sleep&lt;/code&gt; 的时候，执行系统调用 clock_nanosleep，此时控制流跳出了该程序，进入了操作系统的系统调用实现代码，之后操作系统将应用程序A进入睡眠状态，转而运行别的进程，这里体现了异常控制流。在执行其它系统调用的时候也会有类似的情况。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;进程&lt;/strong&gt;：整个应用程序A是在一个新的进程中运行的，与启动它的 shell。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;地址空间&lt;/strong&gt;：字符串 &lt;code&gt;hello_string&lt;/code&gt; 所在的地址，是在这个进程自己的地址空间内有效的，和别的进程无关。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文件&lt;/strong&gt;：应用程序A打开文件名为 &lt;code&gt;output.txt&lt;/code&gt; 的文件，向其中写入了一个字符串。此外，&lt;code&gt;printf&lt;/code&gt; 是向标准输出写入，标准输出在此时是一个对应当前终端的文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class=&quot;text-highlight&quot;&gt;操作系统支持应用程序A运行的流程&lt;/span&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;操作系统加载程序和 C 语言标准库到内存中&lt;/li&gt;
&lt;li&gt;操作系统设置一些初始的虚拟内存配置和一些数据，然后切换到用户态跳转到程序的入口点开始运行。&lt;/li&gt;
&lt;li&gt;应用程序调用 C 语言标准库，库再进行系统调用，进入内核，内核处理相关的系统调用然后恢复应用程序运行，具体来说：
&lt;ul&gt;
&lt;li&gt;对于 &lt;code&gt;sleep&lt;/code&gt; 来说，操作系统在 5 秒时间内切换到别的任务，不运行应用程序A，5 秒过后再继续运行&lt;/li&gt;
&lt;li&gt;对于文件来说，操作系统在文件系统内找到对应的文件写入，或者找到对应的终端将写入的内容发送过去&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;最后 C 语言标准库会调用 exit_group 系统调用退出进程。操作系统接收这个系统调用后，不再回到应用程序，释放该进程相关资源。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;10&quot;&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;请简要描述支持单个应用的 OS、批处理 OS、多道程序 OS、分时共享 OS 的特点。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt; ]]></description>
    <pubDate>Sun, 12 Apr 2026 18:00:21 GMT</pubDate>
  </item>
    </channel>
  </rss>