<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="/assets/rss-20b3285f.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>标签: ostep - ouuan's blog</title>
        <link>https://ouuan.moe/tag/ostep</link>
        <description>标签为 ostep 的文章 - ouuan 的博客</description>
        <lastBuildDate>Tue, 06 Feb 2024 16:51:36 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-CN</language>
        <copyright>Copyright © 2022 - 2026 ouuan
Licensed under CC BY-SA 4.0</copyright>
        <atom:link href="https://ouuan.moe/tag/ostep/feed.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[OSTEP 学习笔记 —— Virtualization]]></title>
            <link>https://ouuan.moe/post/2024/01/ostep-virtualization</link>
            <guid>https://ouuan.moe/post/2024/01/ostep-virtualization</guid>
            <pubDate>Tue, 06 Feb 2024 16:51:36 GMT</pubDate>
            <description><![CDATA[



<p><a href="https://pages.cs.wisc.edu/~remzi/OSTEP/"><span class="mojikumi-line-start">《</span>Operating Systems: Three Easy Pieces<span class="mojikumi-line-end">》</span></a>第一部分 Virtualization 的学习笔记<span class="mojikumi-line-end">。</span></p>
]]></description>
            <content:encoded><![CDATA[



<p><a href="https://pages.cs.wisc.edu/~remzi/OSTEP/"><span class="mojikumi-line-start">《</span>Operating Systems: Three Easy Pieces<span class="mojikumi-line-end">》</span></a>第一部分 Virtualization 的学习笔记<span class="mojikumi-line-end">。</span></p>

<h2 id="a-dialogue-on-virtualization" class="heading"><a href="#a-dialogue-on-virtualization" class="heading-anchor" aria-label="章节： A Dialogue on Virtualization" tabindex="-1"></a><span>A Dialogue on Virtualization</span></h2>
<p><s>我觉得这个比喻很怪<span class="mojikumi-line-end">，</span>peach 怎么能 virtualize<span class="mojikumi-line-end">，</span>感觉不如举个别的例子<span class="mojikumi-line-end">。</span>但挑 <code>og:image</code> 的时候想了想<span class="mojikumi-line-end">，</span>这不<span class="mojikumi-line-end">，</span><a href="https://www.bilibili.com/video/av55053935/">桃 channel</a> 吗<span class="mojikumi-line-start">（</span></s></p>
<h2 id="the-abstraction-the-process" class="heading"><a href="#the-abstraction-the-process" class="heading-anchor" aria-label="章节： The Abstraction: The Process" tabindex="-1"></a><span>The Abstraction: The Process</span></h2>
<p>所谓 <dfn>process</dfn><span class="mojikumi-line-end">，</span>就是 <i>a running program</i><span class="mojikumi-line-end">。</span></p>
<p>一个 process 的 machine state 包括 memory<span class="mojikumi-line-end">、</span>register<span class="mojikumi-line-start">（</span>包括 PC<span class="mojikumi-line-end">、</span>stack pointer 等<span class="mojikumi">）</span><span class="mojikumi-line-end">、</span>I/O information<span class="mojikumi-line-start">（</span>例如打开的文件列表<span class="mojikumi-line-end">）</span>等<span class="mojikumi-line-end">。</span></p>
<p>在创建 process 时<span class="mojikumi-line-end">，</span>OS 需要 (lazy) load program code 和 data<span class="mojikumi-line-end">，</span>初始化 stack 和 heap<span class="mojikumi-line-end">，</span>设置 <code>argc</code><span class="mojikumi-line-end">、</span><code>argv</code><span class="mojikumi-line-end">，</span>设置 <code>stdin</code><span class="mojikumi-line-end">、</span><code>stdout</code><span class="mojikumi-line-end">、</span><code>stderr</code> 三个 file descriptor<span class="mojikumi-line-end">。</span></p>
<p>一个 process 有三种 state<span class="mojikumi-line-end">：</span>running<span class="mojikumi-line-end">、</span>blocked<span class="mojikumi-line-end">、</span>ready<span class="mojikumi-line-end">。</span></p>
<div class="flex justify-center dark:hidden">60,115,118,103,32,97,114,105,97,45,114,111,108,101,100,101,115,99,114,105,112,116,105,111,110,61,34,102,108,111,119,99,104,97,114,116,45,118,50,34,32,114,111,108,101,61,34,103,114,97,112,104,105,99,115,45,100,111,99,117,109,101,110,116,32,100,111,99,117,109,101,110,116,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,53,57,51,46,57,53,51,49,50,53,32,49,55,51,34,32,115,116,121,108,101,61,34,109,97,120,45,119,105,100,116,104,58,32,53,57,51,46,57,53,51,112,120,59,32,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,32,116,114,97,110,115,112,97,114,101,110,116,59,34,32,99,108,97,115,115,61,34,102,108,111,119,99,104,97,114,116,34,32,120,109,108,110,115,58,120,108,105,110,107,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,108,105,110,107,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,48,47,115,118,103,34,32,119,105,100,116,104,61,34,49,48,48,37,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,34,62,60,115,116,121,108,101,62,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,123,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,102,111,110,116,45,115,105,122,101,58,49,54,112,120,59,102,105,108,108,58,35,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,114,114,111,114,45,105,99,111,110,123,102,105,108,108,58,35,53,53,50,50,50,50,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,114,114,111,114,45,116,101,120,116,123,102,105,108,108,58,35,53,53,50,50,50,50,59,115,116,114,111,107,101,58,35,53,53,50,50,50,50,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,123,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,116,104,105,99,107,123,115,116,114,111,107,101,45,119,105,100,116,104,58,51,46,53,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,123,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,48,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,105,110,118,105,115,105,98,108,101,123,115,116,114,111,107,101,45,119,105,100,116,104,58,48,59,102,105,108,108,58,110,111,110,101,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,45,112,97,116,116,101,114,110,45,100,97,115,104,101,100,123,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,45,112,97,116,116,101,114,110,45,100,111,116,116,101,100,123,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,50,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,109,97,114,107,101,114,123,102,105,108,108,58,35,51,51,51,51,51,51,59,115,116,114,111,107,101,58,35,51,51,51,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,109,97,114,107,101,114,46,99,114,111,115,115,123,115,116,114,111,107,101,58,35,51,51,51,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,115,118,103,123,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,102,111,110,116,45,115,105,122,101,58,49,54,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,112,123,109,97,114,103,105,110,58,48,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,108,97,98,101,108,123,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,99,111,108,111,114,58,35,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,45,108,97,98,101,108,32,116,101,120,116,123,102,105,108,108,58,35,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,45,108,97,98,101,108,32,115,112,97,110,123,99,111,108,111,114,58,35,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,45,108,97,98,101,108,32,115,112,97,110,32,112,123,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,116,114,97,110,115,112,97,114,101,110,116,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,108,97,98,101,108,32,116,101,120,116,44,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,115,112,97,110,123,102,105,108,108,58,35,51,51,51,59,99,111,108,111,114,58,35,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,32,114,101,99,116,44,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,32,99,105,114,99,108,101,44,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,32,101,108,108,105,112,115,101,44,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,32,112,111,108,121,103,111,110,44,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,32,112,97,116,104,123,102,105,108,108,58,35,69,67,69,67,70,70,59,115,116,114,111,107,101,58,35,57,51,55,48,68,66,59,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,114,111,117,103,104,45,110,111,100,101,32,46,108,97,98,101,108,32,116,101,120,116,44,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,32,46,108,97,98,101,108,32,116,101,120,116,123,116,101,120,116,45,97,110,99,104,111,114,58,109,105,100,100,108,101,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,32,46,107,97,116,101,120,32,112,97,116,104,123,102,105,108,108,58,35,48,48,48,59,115,116,114,111,107,101,58,35,48,48,48,59,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,32,46,108,97,98,101,108,123,116,101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,110,111,100,101,46,99,108,105,99,107,97,98,108,101,123,99,117,114,115,111,114,58,112,111,105,110,116,101,114,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,97,114,114,111,119,104,101,97,100,80,97,116,104,123,102,105,108,108,58,35,51,51,51,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,80,97,116,104,32,46,112,97,116,104,123,115,116,114,111,107,101,58,35,51,51,51,51,51,51,59,115,116,114,111,107,101,45,119,105,100,116,104,58,50,46,48,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,102,108,111,119,99,104,97,114,116,45,108,105,110,107,123,115,116,114,111,107,101,58,35,51,51,51,51,51,51,59,102,105,108,108,58,110,111,110,101,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,76,97,98,101,108,123,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,114,103,98,97,40,50,51,50,44,50,51,50,44,50,51,50,44,32,48,46,56,41,59,116,101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,76,97,98,101,108,32,112,123,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,114,103,98,97,40,50,51,50,44,50,51,50,44,50,51,50,44,32,48,46,56,41,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,101,100,103,101,76,97,98,101,108,32,114,101,99,116,123,111,112,97,99,105,116,121,58,48,46,53,59,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,114,103,98,97,40,50,51,50,44,50,51,50,44,50,51,50,44,32,48,46,56,41,59,102,105,108,108,58,114,103,98,97,40,50,51,50,44,50,51,50,44,50,51,50,44,32,48,46,56,41,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,108,97,98,101,108,66,107,103,123,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,114,103,98,97,40,50,51,50,44,32,50,51,50,44,32,50,51,50,44,32,48,46,53,41,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,32,114,101,99,116,123,102,105,108,108,58,35,102,102,102,102,100,101,59,115,116,114,111,107,101,58,35,97,97,97,97,51,51,59,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,32,116,101,120,116,123,102,105,108,108,58,35,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,32,115,112,97,110,123,99,111,108,111,114,58,35,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,100,105,118,46,109,101,114,109,97,105,100,84,111,111,108,116,105,112,123,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,116,101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,109,97,120,45,119,105,100,116,104,58,50,48,48,112,120,59,112,97,100,100,105,110,103,58,50,112,120,59,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,102,111,110,116,45,115,105,122,101,58,49,50,112,120,59,98,97,99,107,103,114,111,117,110,100,58,104,115,108,40,56,48,44,32,49,48,48,37,44,32,57,54,46,50,55,52,53,48,57,56,48,51,57,37,41,59,98,111,114,100,101,114,58,49,112,120,32,115,111,108,105,100,32,35,97,97,97,97,51,51,59,98,111,114,100,101,114,45,114,97,100,105,117,115,58,50,112,120,59,112,111,105,110,116,101,114,45,101,118,101,110,116,115,58,110,111,110,101,59,122,45,105,110,100,101,120,58,49,48,48,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,46,102,108,111,119,99,104,97,114,116,84,105,116,108,101,84,101,120,116,123,116,101,120,116,45,97,110,99,104,111,114,58,109,105,100,100,108,101,59,102,111,110,116,45,115,105,122,101,58,49,56,112,120,59,102,105,108,108,58,35,51,51,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,32,58,114,111,111,116,123,45,45,109,101,114,109,97,105,100,45,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,125,60,47,115,116,121,108,101,62,60,103,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,56,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,56,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,34,32,114,101,102,88,61,34,53,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,48,32,49,48,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,34,62,60,112,97,116,104,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,49,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,100,61,34,77,32,48,32,48,32,76,32,49,48,32,53,32,76,32,48,32,49,48,32,122,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,56,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,56,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,34,32,114,101,102,88,61,34,52,46,53,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,48,32,49,48,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,83,116,97,114,116,34,62,60,112,97,116,104,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,49,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,100,61,34,77,32,48,32,53,32,76,32,49,48,32,49,48,32,76,32,49,48,32,48,32,122,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,49,49,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,49,49,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,34,32,114,101,102,88,61,34,49,49,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,48,32,49,48,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,99,105,114,99,108,101,69,110,100,34,62,60,99,105,114,99,108,101,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,49,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,114,61,34,53,34,32,99,121,61,34,53,34,32,99,120,61,34,53,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,49,49,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,49,49,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,34,32,114,101,102,88,61,34,45,49,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,48,32,49,48,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,99,105,114,99,108,101,83,116,97,114,116,34,62,60,99,105,114,99,108,101,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,49,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,114,61,34,53,34,32,99,121,61,34,53,34,32,99,120,61,34,53,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,49,49,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,49,49,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,46,50,34,32,114,101,102,88,61,34,49,50,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,49,32,49,49,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,99,114,111,115,115,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,99,114,111,115,115,69,110,100,34,62,60,112,97,116,104,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,50,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,100,61,34,77,32,49,44,49,32,108,32,57,44,57,32,77,32,49,48,44,49,32,108,32,45,57,44,57,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,49,49,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,49,49,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,46,50,34,32,114,101,102,88,61,34,45,49,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,49,32,49,49,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,99,114,111,115,115,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,99,114,111,115,115,83,116,97,114,116,34,62,60,112,97,116,104,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,50,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,100,61,34,77,32,49,44,49,32,108,32,57,44,57,32,77,32,49,48,44,49,32,108,32,45,57,44,57,34,47,62,60,47,109,97,114,107,101,114,62,60,103,32,99,108,97,115,115,61,34,114,111,111,116,34,62,60,103,32,99,108,97,115,115,61,34,99,108,117,115,116,101,114,115,34,47,62,60,103,32,99,108,97,115,115,61,34,101,100,103,101,80,97,116,104,115,34,62,60,112,97,116,104,32,109,97,114,107,101,114,45,101,110,100,61,34,117,114,108,40,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,102,108,111,119,99,104,97,114,116,45,108,105,110,107,34,32,105,100,61,34,76,95,82,117,110,110,105,110,103,95,66,108,111,99,107,101,100,95,48,34,32,100,61,34,77,49,49,49,46,56,56,56,44,56,50,76,49,50,52,46,54,55,55,44,55,52,46,49,54,55,67,49,51,55,46,52,54,55,44,54,54,46,51,51,51,44,49,54,51,46,48,52,54,44,53,48,46,54,54,55,44,49,56,48,46,57,50,44,52,50,46,56,51,51,67,49,57,56,46,55,57,52,44,51,53,44,50,48,56,46,57,54,52,44,51,53,44,50,49,56,46,52,54,54,44,51,53,67,50,50,55,46,57,54,57,44,51,53,44,50,51,54,46,56,48,53,44,51,53,44,50,52,49,46,50,50,51,44,51,53,76,50,52,53,46,54,52,49,44,51,53,34,47,62,60,112,97,116,104,32,109,97,114,107,101,114,45,101,110,100,61,34,117,114,108,40,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,102,108,111,119,99,104,97,114,116,45,108,105,110,107,34,32,105,100,61,34,76,95,66,108,111,99,107,101,100,95,82,101,97,100,121,95,49,34,32,100,61,34,77,51,54,54,46,53,54,51,44,51,53,76,51,55,53,46,57,57,49,44,51,53,67,51,56,53,46,52,49,57,44,51,53,44,52,48,52,46,50,55,54,44,51,53,44,52,49,57,46,53,49,44,51,56,46,57,49,55,67,52,51,52,46,55,52,53,44,52,50,46,56,51,51,44,52,52,54,46,51,53,55,44,53,48,46,54,54,55,44,52,53,55,46,52,49,54,44,53,56,46,49,50,55,67,52,54,56,46,52,55,53,44,54,53,46,53,56,56,44,52,55,56,46,57,56,50,44,55,50,46,54,55,53,44,52,56,52,46,50,51,53,44,55,54,46,50,49,57,76,52,56,57,46,52,56,56,44,55,57,46,55,54,51,34,47,62,60,112,97,116,104,32,109,97,114,107,101,114,45,101,110,100,61,34,117,114,108,40,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,102,108,111,119,99,104,97,114,116,45,108,105,110,107,34,32,105,100,61,34,76,95,82,101,97,100,121,95,82,117,110,110,105,110,103,95,50,34,32,100,61,34,77,52,55,57,46,55,48,51,44,49,51,48,46,51,48,57,76,52,55,48,46,50,55,53,44,49,51,52,46,48,57,49,67,52,54,48,46,56,52,54,44,49,51,55,46,56,55,51,44,52,52,49,46,57,57,44,49,52,53,46,52,51,54,44,52,49,51,46,51,56,57,44,49,52,57,46,50,49,56,67,51,56,52,46,55,56,57,44,49,53,51,44,51,52,54,46,52,52,53,44,49,53,51,44,51,48,55,46,51,54,49,44,49,53,51,67,50,54,56,46,50,55,54,44,49,53,51,44,50,50,56,46,52,53,49,44,49,53,51,44,50,48,51,46,52,53,51,44,49,53,49,46,49,52,56,67,49,55,56,46,52,53,54,44,49,52,57,46,50,57,55,44,49,54,56,46,50,56,54,44,49,52,53,46,53,57,51,44,49,53,56,46,55,52,52,44,49,52,50,46,49,49,56,67,49,52,57,46,50,48,49,44,49,51,56,46,54,52,51,44,49,52,48,46,50,56,52,44,49,51,53,46,51,57,53,44,49,51,53,46,56,50,54,44,49,51,51,46,55,55,50,76,49,51,49,46,51,54,56,44,49,51,50,46,49,52,56,34,47,62,60,112,97,116,104,32,109,97,114,107,101,114,45,101,110,100,61,34,117,114,108,40,35,95,95,109,101,114,109,97,105,100,45,100,101,102,97,117,108,116,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,102,108,111,119,99,104,97,114,116,45,108,105,110,107,34,32,105,100,61,34,76,95,82,117,110,110,105,110,103,95,82,101,97,100,121,95,51,34,32,100,61,34,77,49,50,55,46,54,48,57,44,49,48,57,76,49,51,55,46,55,55,57,44,49,48,57,67,49,52,55,46,57,52,56,44,49,48,57,44,49,54,56,46,50,56,54,44,49,48,57,44,49,57,56,46,51,54,56,44,49,48,57,67,50,50,56,46,52,53,49,44,49,48,57,44,50,54,56,46,50,55,54,44,49,48,57,44,51,48,55,46,51,54,49,44,49,48,57,67,51,52,54,46,52,52,53,44,49,48,57,44,51,56,52,46,55,56,57,44,49,48,57,44,52,48,56,46,54,55,53,44,49,48,57,67,52,51,50,46,53,54,49,44,49,48,57,44,52,52,49,46,57,57,44,49,48,57,44,52,53,48,46,55,53,49,44,49,48,57,67,52,53,57,46,53,49,51,44,49,48,57,44,52,54,55,46,54,48,56,44,49,48,57,44,52,55,49,46,54,53,54,44,49,48,57,76,52,55,53,46,55,48,51,44,49,48,57,34,47,62,60,47,103,62,60,103,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,115,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,49,56,56,46,54,50,53,44,32,51,53,41,34,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,51,54,46,48,49,53,54,50,53,44,32,45,49,50,41,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,55,50,46,48,51,49,50,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,99,108,97,115,115,61,34,108,97,98,101,108,66,107,103,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,112,62,105,110,105,116,105,97,116,101,32,73,47,79,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,52,50,51,46,49,51,50,56,49,50,53,44,32,51,53,41,34,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,51,49,46,53,55,48,51,49,50,53,44,32,45,49,50,41,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,54,51,46,49,52,48,54,50,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,99,108,97,115,115,61,34,108,97,98,101,108,66,107,103,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,112,62,102,105,110,105,115,104,32,73,47,79,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,51,48,56,46,49,48,49,53,54,50,53,44,32,49,53,51,41,34,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,51,50,46,48,50,51,52,51,55,53,44,32,45,49,50,41,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,54,52,46,48,52,54,56,55,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,99,108,97,115,115,61,34,108,97,98,101,108,66,107,103,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,112,62,115,99,104,101,100,117,108,101,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,51,48,56,46,49,48,49,53,54,50,53,44,32,49,48,57,41,34,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,52,48,46,57,50,49,56,55,53,44,32,45,49,50,41,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,56,49,46,56,52,51,55,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,99,108,97,115,115,61,34,108,97,98,101,108,66,107,103,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,112,62,100,101,115,99,104,101,100,117,108,101,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,47,103,62,60,103,32,99,108,97,115,115,61,34,110,111,100,101,115,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,54,55,46,56,48,52,54,56,55,53,44,32,49,48,57,41,34,32,105,100,61,34,102,108,111,119,99,104,97,114,116,45,82,117,110,110,105,110,103,45,48,34,32,99,108,97,115,115,61,34,110,111,100,101,32,100,101,102,97,117,108,116,34,62,60,114,101,99,116,32,104,101,105,103,104,116,61,34,53,52,34,32,119,105,100,116,104,61,34,49,49,57,46,54,48,57,51,55,53,34,32,121,61,34,45,50,55,34,32,120,61,34,45,53,57,46,56,48,52,54,56,55,53,34,32,100,97,116,97,45,101,116,61,34,110,111,100,101,34,32,100,97,116,97,45,105,100,61,34,97,98,99,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,98,97,115,105,99,32,108,97,98,101,108,45,99,111,110,116,97,105,110,101,114,34,47,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,50,57,46,56,48,52,54,56,55,53,44,32,45,49,50,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,114,101,99,116,47,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,53,57,46,54,48,57,51,55,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,110,111,100,101,76,97,98,101,108,34,62,60,112,62,82,117,110,110,105,110,103,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,51,48,56,46,49,48,49,53,54,50,53,44,32,51,53,41,34,32,105,100,61,34,102,108,111,119,99,104,97,114,116,45,66,108,111,99,107,101,100,45,49,34,32,99,108,97,115,115,61,34,110,111,100,101,32,100,101,102,97,117,108,116,34,62,60,114,101,99,116,32,104,101,105,103,104,116,61,34,53,52,34,32,119,105,100,116,104,61,34,49,49,54,46,57,50,49,56,55,53,34,32,121,61,34,45,50,55,34,32,120,61,34,45,53,56,46,52,54,48,57,51,55,53,34,32,100,97,116,97,45,101,116,61,34,110,111,100,101,34,32,100,97,116,97,45,105,100,61,34,97,98,99,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,98,97,115,105,99,32,108,97,98,101,108,45,99,111,110,116,97,105,110,101,114,34,47,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,50,56,46,52,54,48,57,51,55,53,44,32,45,49,50,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,114,101,99,116,47,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,53,54,46,57,50,49,56,55,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,110,111,100,101,76,97,98,101,108,34,62,60,112,62,66,108,111,99,107,101,100,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,53,51,50,46,56,50,56,49,50,53,44,32,49,48,57,41,34,32,105,100,61,34,102,108,111,119,99,104,97,114,116,45,82,101,97,100,121,45,50,34,32,99,108,97,115,115,61,34,110,111,100,101,32,100,101,102,97,117,108,116,34,62,60,114,101,99,116,32,104,101,105,103,104,116,61,34,53,52,34,32,119,105,100,116,104,61,34,49,48,54,46,50,53,34,32,121,61,34,45,50,55,34,32,120,61,34,45,53,51,46,49,50,53,34,32,100,97,116,97,45,101,116,61,34,110,111,100,101,34,32,100,97,116,97,45,105,100,61,34,97,98,99,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,98,97,115,105,99,32,108,97,98,101,108,45,99,111,110,116,97,105,110,101,114,34,47,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,50,51,46,49,50,53,44,32,45,49,50,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,114,101,99,116,47,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,52,54,46,50,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,110,111,100,101,76,97,98,101,108,34,62,60,112,62,82,101,97,100,121,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,47,103,62,60,47,103,62,60,47,103,62,60,47,115,118,103,62</div><div class="justify-center dark:important-flex" style="display:none;">60,115,118,103,32,97,114,105,97,45,114,111,108,101,100,101,115,99,114,105,112,116,105,111,110,61,34,102,108,111,119,99,104,97,114,116,45,118,50,34,32,114,111,108,101,61,34,103,114,97,112,104,105,99,115,45,100,111,99,117,109,101,110,116,32,100,111,99,117,109,101,110,116,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,53,57,51,46,57,53,51,49,50,53,32,49,55,51,34,32,115,116,121,108,101,61,34,109,97,120,45,119,105,100,116,104,58,32,53,57,51,46,57,53,51,112,120,59,32,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,32,116,114,97,110,115,112,97,114,101,110,116,59,34,32,99,108,97,115,115,61,34,102,108,111,119,99,104,97,114,116,34,32,120,109,108,110,115,58,120,108,105,110,107,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,108,105,110,107,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,48,47,115,118,103,34,32,119,105,100,116,104,61,34,49,48,48,37,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,34,62,60,115,116,121,108,101,62,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,123,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,102,111,110,116,45,115,105,122,101,58,49,54,112,120,59,102,105,108,108,58,35,99,99,99,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,114,114,111,114,45,105,99,111,110,123,102,105,108,108,58,35,97,52,52,49,52,49,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,114,114,111,114,45,116,101,120,116,123,102,105,108,108,58,35,100,100,100,59,115,116,114,111,107,101,58,35,100,100,100,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,123,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,116,104,105,99,107,123,115,116,114,111,107,101,45,119,105,100,116,104,58,51,46,53,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,123,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,48,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,105,110,118,105,115,105,98,108,101,123,115,116,114,111,107,101,45,119,105,100,116,104,58,48,59,102,105,108,108,58,110,111,110,101,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,45,112,97,116,116,101,114,110,45,100,97,115,104,101,100,123,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,51,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,45,112,97,116,116,101,114,110,45,100,111,116,116,101,100,123,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,50,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,109,97,114,107,101,114,123,102,105,108,108,58,108,105,103,104,116,103,114,101,121,59,115,116,114,111,107,101,58,108,105,103,104,116,103,114,101,121,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,109,97,114,107,101,114,46,99,114,111,115,115,123,115,116,114,111,107,101,58,108,105,103,104,116,103,114,101,121,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,115,118,103,123,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,102,111,110,116,45,115,105,122,101,58,49,54,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,112,123,109,97,114,103,105,110,58,48,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,108,97,98,101,108,123,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,99,111,108,111,114,58,35,99,99,99,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,45,108,97,98,101,108,32,116,101,120,116,123,102,105,108,108,58,35,70,57,70,70,70,69,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,45,108,97,98,101,108,32,115,112,97,110,123,99,111,108,111,114,58,35,70,57,70,70,70,69,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,45,108,97,98,101,108,32,115,112,97,110,32,112,123,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,116,114,97,110,115,112,97,114,101,110,116,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,108,97,98,101,108,32,116,101,120,116,44,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,115,112,97,110,123,102,105,108,108,58,35,99,99,99,59,99,111,108,111,114,58,35,99,99,99,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,32,114,101,99,116,44,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,32,99,105,114,99,108,101,44,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,32,101,108,108,105,112,115,101,44,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,32,112,111,108,121,103,111,110,44,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,32,112,97,116,104,123,102,105,108,108,58,35,49,102,50,48,50,48,59,115,116,114,111,107,101,58,35,99,99,99,59,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,114,111,117,103,104,45,110,111,100,101,32,46,108,97,98,101,108,32,116,101,120,116,44,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,32,46,108,97,98,101,108,32,116,101,120,116,123,116,101,120,116,45,97,110,99,104,111,114,58,109,105,100,100,108,101,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,32,46,107,97,116,101,120,32,112,97,116,104,123,102,105,108,108,58,35,48,48,48,59,115,116,114,111,107,101,58,35,48,48,48,59,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,32,46,108,97,98,101,108,123,116,101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,110,111,100,101,46,99,108,105,99,107,97,98,108,101,123,99,117,114,115,111,114,58,112,111,105,110,116,101,114,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,97,114,114,111,119,104,101,97,100,80,97,116,104,123,102,105,108,108,58,108,105,103,104,116,103,114,101,121,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,80,97,116,104,32,46,112,97,116,104,123,115,116,114,111,107,101,58,108,105,103,104,116,103,114,101,121,59,115,116,114,111,107,101,45,119,105,100,116,104,58,50,46,48,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,102,108,111,119,99,104,97,114,116,45,108,105,110,107,123,115,116,114,111,107,101,58,108,105,103,104,116,103,114,101,121,59,102,105,108,108,58,110,111,110,101,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,76,97,98,101,108,123,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,104,115,108,40,48,44,32,48,37,44,32,51,52,46,52,49,49,55,54,52,55,48,53,57,37,41,59,116,101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,76,97,98,101,108,32,112,123,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,104,115,108,40,48,44,32,48,37,44,32,51,52,46,52,49,49,55,54,52,55,48,53,57,37,41,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,101,100,103,101,76,97,98,101,108,32,114,101,99,116,123,111,112,97,99,105,116,121,58,48,46,53,59,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,104,115,108,40,48,44,32,48,37,44,32,51,52,46,52,49,49,55,54,52,55,48,53,57,37,41,59,102,105,108,108,58,104,115,108,40,48,44,32,48,37,44,32,51,52,46,52,49,49,55,54,52,55,48,53,57,37,41,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,108,97,98,101,108,66,107,103,123,98,97,99,107,103,114,111,117,110,100,45,99,111,108,111,114,58,114,103,98,97,40,56,55,46,55,53,44,32,56,55,46,55,53,44,32,56,55,46,55,53,44,32,48,46,53,41,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,32,114,101,99,116,123,102,105,108,108,58,104,115,108,40,49,56,48,44,32,49,46,53,56,55,51,48,49,53,56,55,51,37,44,32,50,56,46,51,53,50,57,52,49,49,55,54,53,37,41,59,115,116,114,111,107,101,58,114,103,98,97,40,50,53,53,44,32,50,53,53,44,32,50,53,53,44,32,48,46,50,53,41,59,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,32,116,101,120,116,123,102,105,108,108,58,35,70,57,70,70,70,69,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,99,108,117,115,116,101,114,32,115,112,97,110,123,99,111,108,111,114,58,35,70,57,70,70,70,69,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,100,105,118,46,109,101,114,109,97,105,100,84,111,111,108,116,105,112,123,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,116,101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,109,97,120,45,119,105,100,116,104,58,50,48,48,112,120,59,112,97,100,100,105,110,103,58,50,112,120,59,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,102,111,110,116,45,115,105,122,101,58,49,50,112,120,59,98,97,99,107,103,114,111,117,110,100,58,104,115,108,40,50,48,44,32,49,46,53,56,55,51,48,49,53,56,55,51,37,44,32,49,50,46,51,53,50,57,52,49,49,55,54,53,37,41,59,98,111,114,100,101,114,58,49,112,120,32,115,111,108,105,100,32,114,103,98,97,40,50,53,53,44,32,50,53,53,44,32,50,53,53,44,32,48,46,50,53,41,59,98,111,114,100,101,114,45,114,97,100,105,117,115,58,50,112,120,59,112,111,105,110,116,101,114,45,101,118,101,110,116,115,58,110,111,110,101,59,122,45,105,110,100,101,120,58,49,48,48,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,46,102,108,111,119,99,104,97,114,116,84,105,116,108,101,84,101,120,116,123,116,101,120,116,45,97,110,99,104,111,114,58,109,105,100,100,108,101,59,102,111,110,116,45,115,105,122,101,58,49,56,112,120,59,102,105,108,108,58,35,99,99,99,59,125,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,32,58,114,111,111,116,123,45,45,109,101,114,109,97,105,100,45,102,111,110,116,45,102,97,109,105,108,121,58,34,116,114,101,98,117,99,104,101,116,32,109,115,34,44,118,101,114,100,97,110,97,44,97,114,105,97,108,44,115,97,110,115,45,115,101,114,105,102,59,125,60,47,115,116,121,108,101,62,60,103,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,56,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,56,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,34,32,114,101,102,88,61,34,53,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,48,32,49,48,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,34,62,60,112,97,116,104,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,49,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,100,61,34,77,32,48,32,48,32,76,32,49,48,32,53,32,76,32,48,32,49,48,32,122,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,56,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,56,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,34,32,114,101,102,88,61,34,52,46,53,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,48,32,49,48,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,83,116,97,114,116,34,62,60,112,97,116,104,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,49,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,100,61,34,77,32,48,32,53,32,76,32,49,48,32,49,48,32,76,32,49,48,32,48,32,122,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,49,49,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,49,49,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,34,32,114,101,102,88,61,34,49,49,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,48,32,49,48,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,99,105,114,99,108,101,69,110,100,34,62,60,99,105,114,99,108,101,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,49,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,114,61,34,53,34,32,99,121,61,34,53,34,32,99,120,61,34,53,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,49,49,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,49,49,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,34,32,114,101,102,88,61,34,45,49,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,48,32,49,48,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,99,105,114,99,108,101,83,116,97,114,116,34,62,60,99,105,114,99,108,101,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,49,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,114,61,34,53,34,32,99,121,61,34,53,34,32,99,120,61,34,53,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,49,49,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,49,49,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,46,50,34,32,114,101,102,88,61,34,49,50,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,49,32,49,49,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,99,114,111,115,115,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,99,114,111,115,115,69,110,100,34,62,60,112,97,116,104,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,50,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,100,61,34,77,32,49,44,49,32,108,32,57,44,57,32,77,32,49,48,44,49,32,108,32,45,57,44,57,34,47,62,60,47,109,97,114,107,101,114,62,60,109,97,114,107,101,114,32,111,114,105,101,110,116,61,34,97,117,116,111,34,32,109,97,114,107,101,114,72,101,105,103,104,116,61,34,49,49,34,32,109,97,114,107,101,114,87,105,100,116,104,61,34,49,49,34,32,109,97,114,107,101,114,85,110,105,116,115,61,34,117,115,101,114,83,112,97,99,101,79,110,85,115,101,34,32,114,101,102,89,61,34,53,46,50,34,32,114,101,102,88,61,34,45,49,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,49,49,32,49,49,34,32,99,108,97,115,115,61,34,109,97,114,107,101,114,32,99,114,111,115,115,32,102,108,111,119,99,104,97,114,116,45,118,50,34,32,105,100,61,34,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,99,114,111,115,115,83,116,97,114,116,34,62,60,112,97,116,104,32,115,116,121,108,101,61,34,115,116,114,111,107,101,45,119,105,100,116,104,58,32,50,59,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,58,32,49,44,32,48,59,34,32,99,108,97,115,115,61,34,97,114,114,111,119,77,97,114,107,101,114,80,97,116,104,34,32,100,61,34,77,32,49,44,49,32,108,32,57,44,57,32,77,32,49,48,44,49,32,108,32,45,57,44,57,34,47,62,60,47,109,97,114,107,101,114,62,60,103,32,99,108,97,115,115,61,34,114,111,111,116,34,62,60,103,32,99,108,97,115,115,61,34,99,108,117,115,116,101,114,115,34,47,62,60,103,32,99,108,97,115,115,61,34,101,100,103,101,80,97,116,104,115,34,62,60,112,97,116,104,32,109,97,114,107,101,114,45,101,110,100,61,34,117,114,108,40,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,102,108,111,119,99,104,97,114,116,45,108,105,110,107,34,32,105,100,61,34,76,95,82,117,110,110,105,110,103,95,66,108,111,99,107,101,100,95,48,34,32,100,61,34,77,49,49,49,46,56,56,56,44,56,50,76,49,50,52,46,54,55,55,44,55,52,46,49,54,55,67,49,51,55,46,52,54,55,44,54,54,46,51,51,51,44,49,54,51,46,48,52,54,44,53,48,46,54,54,55,44,49,56,48,46,57,50,44,52,50,46,56,51,51,67,49,57,56,46,55,57,52,44,51,53,44,50,48,56,46,57,54,52,44,51,53,44,50,49,56,46,52,54,54,44,51,53,67,50,50,55,46,57,54,57,44,51,53,44,50,51,54,46,56,48,53,44,51,53,44,50,52,49,46,50,50,51,44,51,53,76,50,52,53,46,54,52,49,44,51,53,34,47,62,60,112,97,116,104,32,109,97,114,107,101,114,45,101,110,100,61,34,117,114,108,40,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,102,108,111,119,99,104,97,114,116,45,108,105,110,107,34,32,105,100,61,34,76,95,66,108,111,99,107,101,100,95,82,101,97,100,121,95,49,34,32,100,61,34,77,51,54,54,46,53,54,51,44,51,53,76,51,55,53,46,57,57,49,44,51,53,67,51,56,53,46,52,49,57,44,51,53,44,52,48,52,46,50,55,54,44,51,53,44,52,49,57,46,53,49,44,51,56,46,57,49,55,67,52,51,52,46,55,52,53,44,52,50,46,56,51,51,44,52,52,54,46,51,53,55,44,53,48,46,54,54,55,44,52,53,55,46,52,49,54,44,53,56,46,49,50,55,67,52,54,56,46,52,55,53,44,54,53,46,53,56,56,44,52,55,56,46,57,56,50,44,55,50,46,54,55,53,44,52,56,52,46,50,51,53,44,55,54,46,50,49,57,76,52,56,57,46,52,56,56,44,55,57,46,55,54,51,34,47,62,60,112,97,116,104,32,109,97,114,107,101,114,45,101,110,100,61,34,117,114,108,40,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,102,108,111,119,99,104,97,114,116,45,108,105,110,107,34,32,105,100,61,34,76,95,82,101,97,100,121,95,82,117,110,110,105,110,103,95,50,34,32,100,61,34,77,52,55,57,46,55,48,51,44,49,51,48,46,51,48,57,76,52,55,48,46,50,55,53,44,49,51,52,46,48,57,49,67,52,54,48,46,56,52,54,44,49,51,55,46,56,55,51,44,52,52,49,46,57,57,44,49,52,53,46,52,51,54,44,52,49,51,46,51,56,57,44,49,52,57,46,50,49,56,67,51,56,52,46,55,56,57,44,49,53,51,44,51,52,54,46,52,52,53,44,49,53,51,44,51,48,55,46,51,54,49,44,49,53,51,67,50,54,56,46,50,55,54,44,49,53,51,44,50,50,56,46,52,53,49,44,49,53,51,44,50,48,51,46,52,53,51,44,49,53,49,46,49,52,56,67,49,55,56,46,52,53,54,44,49,52,57,46,50,57,55,44,49,54,56,46,50,56,54,44,49,52,53,46,53,57,51,44,49,53,56,46,55,52,52,44,49,52,50,46,49,49,56,67,49,52,57,46,50,48,49,44,49,51,56,46,54,52,51,44,49,52,48,46,50,56,52,44,49,51,53,46,51,57,53,44,49,51,53,46,56,50,54,44,49,51,51,46,55,55,50,76,49,51,49,46,51,54,56,44,49,51,50,46,49,52,56,34,47,62,60,112,97,116,104,32,109,97,114,107,101,114,45,101,110,100,61,34,117,114,108,40,35,95,95,109,101,114,109,97,105,100,45,100,97,114,107,45,103,84,98,86,76,95,102,108,111,119,99,104,97,114,116,45,118,50,45,112,111,105,110,116,69,110,100,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,101,100,103,101,45,116,104,105,99,107,110,101,115,115,45,110,111,114,109,97,108,32,101,100,103,101,45,112,97,116,116,101,114,110,45,115,111,108,105,100,32,102,108,111,119,99,104,97,114,116,45,108,105,110,107,34,32,105,100,61,34,76,95,82,117,110,110,105,110,103,95,82,101,97,100,121,95,51,34,32,100,61,34,77,49,50,55,46,54,48,57,44,49,48,57,76,49,51,55,46,55,55,57,44,49,48,57,67,49,52,55,46,57,52,56,44,49,48,57,44,49,54,56,46,50,56,54,44,49,48,57,44,49,57,56,46,51,54,56,44,49,48,57,67,50,50,56,46,52,53,49,44,49,48,57,44,50,54,56,46,50,55,54,44,49,48,57,44,51,48,55,46,51,54,49,44,49,48,57,67,51,52,54,46,52,52,53,44,49,48,57,44,51,56,52,46,55,56,57,44,49,48,57,44,52,48,56,46,54,55,53,44,49,48,57,67,52,51,50,46,53,54,49,44,49,48,57,44,52,52,49,46,57,57,44,49,48,57,44,52,53,48,46,55,53,49,44,49,48,57,67,52,53,57,46,53,49,51,44,49,48,57,44,52,54,55,46,54,48,56,44,49,48,57,44,52,55,49,46,54,53,54,44,49,48,57,76,52,55,53,46,55,48,51,44,49,48,57,34,47,62,60,47,103,62,60,103,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,115,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,49,56,56,46,54,50,53,44,32,51,53,41,34,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,51,54,46,48,49,53,54,50,53,44,32,45,49,50,41,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,55,50,46,48,51,49,50,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,99,108,97,115,115,61,34,108,97,98,101,108,66,107,103,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,112,62,105,110,105,116,105,97,116,101,32,73,47,79,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,52,50,51,46,49,51,50,56,49,50,53,44,32,51,53,41,34,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,51,49,46,53,55,48,51,49,50,53,44,32,45,49,50,41,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,54,51,46,49,52,48,54,50,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,99,108,97,115,115,61,34,108,97,98,101,108,66,107,103,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,112,62,102,105,110,105,115,104,32,73,47,79,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,51,48,56,46,49,48,49,53,54,50,53,44,32,49,53,51,41,34,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,51,50,46,48,50,51,52,51,55,53,44,32,45,49,50,41,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,54,52,46,48,52,54,56,55,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,99,108,97,115,115,61,34,108,97,98,101,108,66,107,103,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,112,62,115,99,104,101,100,117,108,101,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,51,48,56,46,49,48,49,53,54,50,53,44,32,49,48,57,41,34,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,52,48,46,57,50,49,56,55,53,44,32,45,49,50,41,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,56,49,46,56,52,51,55,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,99,108,97,115,115,61,34,108,97,98,101,108,66,107,103,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,101,100,103,101,76,97,98,101,108,34,62,60,112,62,100,101,115,99,104,101,100,117,108,101,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,47,103,62,60,103,32,99,108,97,115,115,61,34,110,111,100,101,115,34,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,54,55,46,56,48,52,54,56,55,53,44,32,49,48,57,41,34,32,105,100,61,34,102,108,111,119,99,104,97,114,116,45,82,117,110,110,105,110,103,45,48,34,32,99,108,97,115,115,61,34,110,111,100,101,32,100,101,102,97,117,108,116,34,62,60,114,101,99,116,32,104,101,105,103,104,116,61,34,53,52,34,32,119,105,100,116,104,61,34,49,49,57,46,54,48,57,51,55,53,34,32,121,61,34,45,50,55,34,32,120,61,34,45,53,57,46,56,48,52,54,56,55,53,34,32,100,97,116,97,45,101,116,61,34,110,111,100,101,34,32,100,97,116,97,45,105,100,61,34,97,98,99,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,98,97,115,105,99,32,108,97,98,101,108,45,99,111,110,116,97,105,110,101,114,34,47,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,50,57,46,56,48,52,54,56,55,53,44,32,45,49,50,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,114,101,99,116,47,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,53,57,46,54,48,57,51,55,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,110,111,100,101,76,97,98,101,108,34,62,60,112,62,82,117,110,110,105,110,103,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,51,48,56,46,49,48,49,53,54,50,53,44,32,51,53,41,34,32,105,100,61,34,102,108,111,119,99,104,97,114,116,45,66,108,111,99,107,101,100,45,49,34,32,99,108,97,115,115,61,34,110,111,100,101,32,100,101,102,97,117,108,116,34,62,60,114,101,99,116,32,104,101,105,103,104,116,61,34,53,52,34,32,119,105,100,116,104,61,34,49,49,54,46,57,50,49,56,55,53,34,32,121,61,34,45,50,55,34,32,120,61,34,45,53,56,46,52,54,48,57,51,55,53,34,32,100,97,116,97,45,101,116,61,34,110,111,100,101,34,32,100,97,116,97,45,105,100,61,34,97,98,99,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,98,97,115,105,99,32,108,97,98,101,108,45,99,111,110,116,97,105,110,101,114,34,47,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,50,56,46,52,54,48,57,51,55,53,44,32,45,49,50,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,114,101,99,116,47,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,53,54,46,57,50,49,56,55,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,110,111,100,101,76,97,98,101,108,34,62,60,112,62,66,108,111,99,107,101,100,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,53,51,50,46,56,50,56,49,50,53,44,32,49,48,57,41,34,32,105,100,61,34,102,108,111,119,99,104,97,114,116,45,82,101,97,100,121,45,50,34,32,99,108,97,115,115,61,34,110,111,100,101,32,100,101,102,97,117,108,116,34,62,60,114,101,99,116,32,104,101,105,103,104,116,61,34,53,52,34,32,119,105,100,116,104,61,34,49,48,54,46,50,53,34,32,121,61,34,45,50,55,34,32,120,61,34,45,53,51,46,49,50,53,34,32,100,97,116,97,45,101,116,61,34,110,111,100,101,34,32,100,97,116,97,45,105,100,61,34,97,98,99,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,98,97,115,105,99,32,108,97,98,101,108,45,99,111,110,116,97,105,110,101,114,34,47,62,60,103,32,116,114,97,110,115,102,111,114,109,61,34,116,114,97,110,115,108,97,116,101,40,45,50,51,46,49,50,53,44,32,45,49,50,41,34,32,115,116,121,108,101,61,34,34,32,99,108,97,115,115,61,34,108,97,98,101,108,34,62,60,114,101,99,116,47,62,60,102,111,114,101,105,103,110,79,98,106,101,99,116,32,104,101,105,103,104,116,61,34,50,52,34,32,119,105,100,116,104,61,34,52,54,46,50,53,34,62,60,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,97,121,58,32,116,97,98,108,101,45,99,101,108,108,59,32,119,104,105,116,101,45,115,112,97,99,101,58,32,110,111,119,114,97,112,59,32,108,105,110,101,45,104,101,105,103,104,116,58,32,49,46,53,59,32,109,97,120,45,119,105,100,116,104,58,32,50,48,48,112,120,59,32,116,101,120,116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,115,112,97,110,32,99,108,97,115,115,61,34,110,111,100,101,76,97,98,101,108,34,62,60,112,62,82,101,97,100,121,60,47,112,62,60,47,115,112,97,110,62,60,47,100,105,118,62,60,47,102,111,114,101,105,103,110,79,98,106,101,99,116,62,60,47,103,62,60,47,103,62,60,47,103,62,60,47,103,62,60,47,103,62,60,47,115,118,103,62</div>
<p>OS 的 scheduler 需要决定如何调度 process state<span class="mojikumi-line-end">，</span>以优化性能<span class="mojikumi-line-end">。</span>例如<span class="mojikumi-line-end">，</span>一个 process initiate I/O 后应当 schedule 到另一个 ready 的 process<span class="mojikumi-line-end">。</span></p>
<p>OS 需要维护 process list<span class="mojikumi-line-end">，</span>记录 process memory address<span class="mojikumi-line-end">、</span>kernel stack address<span class="mojikumi-line-end">、</span>register context<span class="mojikumi-line-end">、</span>process state<span class="mojikumi-line-end">、</span>pid<span class="mojikumi-line-end">、</span>parent<span class="mojikumi-line-end">、</span>killed<span class="mojikumi-line-end">、</span>opened files<span class="mojikumi-line-end">、</span>cwd<span class="mojikumi-line-end">、</span>trap frame 等信息<span class="mojikumi-line-end">。</span></p>
<h2 id="interlude-process-api" class="heading"><a href="#interlude-process-api" class="heading-anchor" aria-label="章节： Interlude: Process API" tabindex="-1"></a><span>Interlude: Process API</span></h2>
<p><code>fork()</code><span class="mojikumi-line-end">、</span><code>wait()</code><span class="mojikumi-line-end">、</span><code>exec()</code> 以及 signals 参见 <a href="/post/2022/11/csapp-8#process-control">CS:APP 第八章</a><span class="mojikumi-line-end">。</span></p>
<p><code>fork()</code> 和 <code>exec()</code> 通常配合使用<span class="mojikumi-line-end">，</span>而被设计成了分离的两个 API<span class="mojikumi-line-end">，</span>所以可以在它们之间插入其他代码<span class="mojikumi-line-end">，</span>以修改 child process 的执行环境<span class="mojikumi-line-end">。</span>例如<span class="mojikumi-line-end">，</span>在 shell 中执行命令可以创建 child process 然后 wait<span class="mojikumi-line-end">，</span>如果需要 redirect output<span class="mojikumi-line-end">，</span>可以在 <code>fork()</code> 和 <code>exec()</code> 之间执行 <code>close()</code> 和 <code>open()</code><span class="mojikumi-line-end">。</span></p>
<a id="a-fork-in-the-road" name="a-fork-in-the-road" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-blue-1 dark:bg-blue-9 b-blue" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-pencil text-blue" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Note: </span><span data-v-a2ab257f>A <code>fork()</code> in the road</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><ul>
<li>论文<span class="mojikumi-line-end">：</span><a href="https://www.microsoft.com/en-us/research/uploads/prod/2019/04/fork-hotos19.pdf">A fork() in the road</a></li>
<li>相关讨论<span class="mojikumi-line-end">：</span><a href="https://lwn.net/Articles/785430/">LWN</a><span class="mojikumi-line-end">、</span><a href="https://www.reddit.com/r/programming/comments/bbic2e/a_fork_in_the_road/">Reddit</a><span class="mojikumi-line-end">、</span><a href="https://news.ycombinator.com/item?id=19621799">Hacker News</a></li>
</ul><p><code>fork()</code> 的设计有很多缺点<span class="mojikumi-line-end">：</span>新功能的设计需要考虑到 <code>fork()</code><span class="mojikumi-line-start">（</span>新的状态如何复制<span class="mojikumi-line-end">）</span>而变得复杂<span class="mojikumi-line-end">，</span>有时需要特殊修改软件来适配 <code>fork()</code><span class="mojikumi-line-start">（</span>例如 buffered I/O 在 fork 前需要 flush<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>有的硬件<span class="mojikumi-line-start">（</span>例如 GPU<span class="mojikumi-line-end">）</span>不支持复制状态<span class="mojikumi-line-end">，</span><code>fork()</code> 不 thread-safe<span class="mojikumi-line-end">，</span>将所有信息共享给 child process 可能泄露信息<span class="mojikumi-line-end">，</span>保持 memory layout 不变可能导致 ASLR 失效<span class="mojikumi-line-end">，</span>不必要地复制整个 address space 会影响性能<span class="mojikumi-line-end">，</span>不管剩余 RAM 有多少就分配 copy-on-write memory<span class="mojikumi-line-start">（</span>overcommit<span class="mojikumi-line-end">）</span>可能导致 OOM<span class="mojikumi-line-end">，</span>支持 copy-on-write 会鼓励 monolith kernel……</p><p><code>fork()</code> 历史悠久<span class="mojikumi-line-end">，</span>使用广泛<span class="mojikumi-line-end">，</span>如果 OS 不实现则会使得很多程序无法运行<span class="mojikumi-line-end">。</span>但在理论上<span class="mojikumi-line-end">，</span><code>fork()</code> 可能可以被替换<span class="mojikumi-line-end">：</span></p><ul>
<li><code>fork()</code> + <code>exec()</code> 创建 child process 可以替换为合二为一的 (<code>posix_</code>)<code>spawn()</code><span class="mojikumi-line-end">。</span></li>
<li><code>spawn()</code> 的参数可能不够灵活<span class="mojikumi-line-end">，</span>可以添加 cross-process operation 来代替位于 <code>fork()</code> 和 <code>exec()</code> 之间的任意操作<span class="mojikumi">。</span><wbr><span class="mojikumi-line-start">（</span>但这样的替代可能不够简洁直观<span class="mojikumi">。</span><span class="mojikumi-line-end">）</span></li>
<li>使用 <code>fork()</code> 来实现 multi-process 可以替换为 multi-thread<span class="mojikumi-line-end">，</span>或者创建全新的 child process<span class="mojikumi">。</span><wbr><span class="mojikumi-line-start">（</span>但这样的话就不能共享初始化<span class="mojikumi-line-end">，</span>可能会有一定的性能损失<span class="mojikumi">。</span><span class="mojikumi-line-end">）</span></li>
<li>可以增加新的 API 来代替使用 <code>fork()</code> 获取 copy-on-write memory<span class="mojikumi">。</span><wbr><span class="mojikumi-line-start">（</span>可能仍会面临 overcommit 的问题<span class="mojikumi">。</span><span class="mojikumi-line-end">）</span></li>
<li>对于少量仍需使用 <code>fork()</code> 而性能要求不高的场景<span class="mojikumi-line-end">，</span>或者是为了兼容使用 <code>fork()</code> 的软件<span class="mojikumi-line-end">，</span>可以抛弃 low-level 的 <code>fork()</code> 而在 high-level<span class="mojikumi-line-start">（</span>低效地<span class="mojikumi-line-end">）</span>实现这一功能<span class="mojikumi-line-end">。</span></li>
</ul></div></div></aside>
<h2 id="mechanism-limited-direct-execution" class="heading"><a href="#mechanism-limited-direct-execution" class="heading-anchor" aria-label="章节： Mechanism: Limited Direct Execution" tabindex="-1"></a><span>Mechanism: Limited Direct Execution</span></h2>
<p><span class="mojikumi-line-start">“</span>direct execution<span class="mojikumi">”</span> 就是直接执行一个 program<span class="mojikumi-line-end">，</span>但这样做无法对 user program 进行限制<span class="mojikumi-line-end">，</span>例如可能访问包括 kernel memory<span class="mojikumi-line-end">、</span>其他 process 在内的任意 memory<span class="mojikumi-line-end">、</span>一直运行而不把 control 交给 OS<span class="mojikumi-line-end">。</span>所以<span class="mojikumi-line-end">，</span>OS 需要采用 <i>limited direct execution</i><span class="mojikumi-line-end">，</span>对 process 施加限制<span class="mojikumi-line-end">。</span>这样做虽然 <span class="mojikumi">“</span>limited<span class="mojikumi">”</span><span class="mojikumi-line-end">，</span>但依然是 CPU 直接执行 user program instruction<span class="mojikumi-line-end">，</span>所以不会有太多的 overhead<span class="mojikumi-line-end">。</span></p>
<h3 id="problem-1-restricted-operations" class="heading"><a href="#problem-1-restricted-operations" class="heading-anchor" aria-label="章节： Problem #1: Restricted Operations" tabindex="-1"></a><span>Problem #1: Restricted Operations</span></h3>
<p>为了限制 user program 的行为<span class="mojikumi-line-end">，</span>CPU 的执行分为 <i>user mode</i> 和 <i>kernel mode</i><span class="mojikumi-line-end">。</span>kernel mode 具有更高的权限<span class="mojikumi-line-end">，</span>例如可以直接访问 memory<span class="mojikumi-line-end">、</span>执行 I/O<span class="mojikumi-line-end">。</span></p>
<p>user program 需要通过 <i>system call</i> 来进入 kernel mode<span class="mojikumi-line-end">，</span>由 OS 执行相应的操作<span class="mojikumi-line-end">。</span>system call 是一种特殊的 <i>trap</i><span class="mojikumi-line-start">（</span>exception<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>通过 trap instruction 进入 <i>trap handler</i> 并把 register 等状态存下来<span class="mojikumi-line-end">，</span>操作执行完毕后再 return-from-trap 回到 user program 调用 system call 之后的位置并恢复 register 等状态<span class="mojikumi-line-end">。</span></p>
<p>在系统启动时<span class="mojikumi-line-end">，</span>OS 会设置 <i>trap table</i><span class="mojikumi-line-end">，</span>即各种 trap 对应的 handler address<span class="mojikumi-line-end">。</span><i>system-call number</i><span class="mojikumi-line-start">（</span>放在特定 register 或 stack 特定位置<span class="mojikumi-line-end">）</span>用来指定要执行哪个 system call<span class="mojikumi-line-end">。</span>trap table 只能由 OS 设定<span class="mojikumi-line-end">，</span>以避免 user program 任意指定 kernel mode 下跳转到的位置<span class="mojikumi-line-end">。</span></p>
<h3 id="problem-2-switching-between-processes" class="heading"><a href="#problem-2-switching-between-processes" class="heading-anchor" aria-label="章节： Problem #2: Switching Between Processes" tabindex="-1"></a><span>Problem #2: Switching Between Processes</span></h3>
<p>在一个 process 占用着 CPU 时<span class="mojikumi-line-end">，</span>OS 没有运行<span class="mojikumi-line-end">，</span>自然无法实现 control<span class="mojikumi-line-end">，</span>所以需要 user program 把 control 交给 OS<span class="mojikumi-line-end">。</span>这有两种方式<span class="mojikumi-line-end">，</span>一种是 cooperative approach<span class="mojikumi-line-end">，</span>即调用 system call<span class="mojikumi-line-end">；</span>一种是 non-cooperative approach<span class="mojikumi-line-end">，</span>即使用 timer interrupt<span class="mojikumi-line-end">，</span>每隔一段时间就把 control 强制交给 OS<span class="mojikumi-line-end">，</span>以避免单个 process 连续运行过长时间甚至进入死循环而只能重启<span class="mojikumi-line-end">。</span></p>
<p>决定了要切换 process 时<span class="mojikumi-line-end">，</span>OS 会进行 <i>context switch</i><span class="mojikumi-line-end">，</span>主要操作是从 process A 的 registers 和 kernel stack 切换到 process B 的 registers 和 kernel stack<span class="mojikumi-line-end">，</span>之后 return-from-trap 时就会返回到 process B 之前离开的地方<span class="mojikumi-line-end">。</span></p>
<h2 id="scheduling-introduction" class="heading"><a href="#scheduling-introduction" class="heading-anchor" aria-label="章节： Scheduling: Introduction" tabindex="-1"></a><span>Scheduling: Introduction</span></h2>
<p>OS scheduler 需要决定 schedule 到哪个 process<span class="mojikumi-line-end">，</span>这表现为 <i>scheduling policy</i> (<i>discipline</i>)<span class="mojikumi-line-end">。</span></p>
<h3 id="workload-assumptions" class="heading"><a href="#workload-assumptions" class="heading-anchor" aria-label="章节： Workload Assumptions" tabindex="-1"></a><span>Workload Assumptions</span></h3>
<p>在这一部分<span class="mojikumi-line-end">，</span>我们先对 <i>workload</i><span class="mojikumi-line-end">，</span>即需要运行的 processes<span class="mojikumi-line-start">（</span>即 jobs<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>作一些<span class="mojikumi-line-start">（</span>不切实际的<span class="mojikumi-line-end">）</span>assumption 以简化问题<span class="mojikumi-line-end">，</span>后面再逐步丢弃这些 assumption<span class="mojikumi-line-end">：</span></p>
<ol>
<li>每个 job 用时相同<span class="mojikumi-line-end">。</span></li>
<li>每个 job 同时 arrive<span class="mojikumi-line-end">。</span></li>
<li>每个 job 一旦开始就一直运行到结束<span class="mojikumi-line-end">，</span>不被打断<span class="mojikumi-line-end">。</span></li>
<li>每个 job 都只使用 CPU<span class="mojikumi-line-end">，</span>不使用 I/O<span class="mojikumi-line-start">（</span>没有 system call<span class="mojikumi-line-end">，</span>不会 blocked<span class="mojikumi">）</span><span class="mojikumi-line-end">。</span></li>
<li>每个 job 的用时是已知的<span class="mojikumi-line-end">。</span></li>
</ol>
<p>其中<span class="mojikumi-line-end">，</span>4 和 5 是最不切实际的<span class="mojikumi-line-end">：</span>没有 I/O 的 program 运行了没有任何意义<span class="mojikumi-line-end">；</span>scheduler 无法预知 job 要运行多久<span class="mojikumi-line-start">（</span>连是否停机都无法预知<span class="mojikumi">）</span><span class="mojikumi-line-end">。</span></p>
<h3 id="turnaround-time" class="heading"><a href="#turnaround-time" class="heading-anchor" aria-label="章节： Turnaround Time" tabindex="-1"></a><span>Turnaround Time</span></h3>
<p><i>turnaround time</i> 是一个 <i>scheduling metric</i><span class="mojikumi-line-end">，</span>它指的是一个 job 从 arrival 到 completion 的用时<span class="mojikumi-line-end">，</span>用来衡量总体性能<span class="mojikumi-line-end">。</span></p>
<p>FIFO (first in first out / FCFS, first come first served) 是一种最简单的 scheduling policy<span class="mojikumi-line-end">。</span>在所有 5 个 assumption 下<span class="mojikumi-line-end">，</span>任何 scheduling policy 都是一样的<span class="mojikumi-line-end">，</span>FIFO 就可以达到最优<span class="mojikumi-line-end">。</span></p>
<p>如果丢弃 assumption 1 而继续使用 FIFO<span class="mojikumi-line-end">，</span>当排在最前的 job 用时很长时<span class="mojikumi-line-end">，</span>会造成 <i>convoy effect</i><span class="mojikumi-line-end">，</span>堵住后面用时短的其他 job<span class="mojikumi-line-end">，</span>使得 turnaround time 变得很大<span class="mojikumi-line-end">。</span>此时<span class="mojikumi-line-end">，</span>可以采用 SJF (shortest job first) 达到最优解<span class="mojikumi-line-end">。</span></p>
<p>如果进一步丢弃 assumption 2<span class="mojikumi-line-end">，</span>有可能最长的 job 最先到<span class="mojikumi-line-end">，</span>短的 job 紧随其后<span class="mojikumi-line-end">，</span>SJF 就失效了<span class="mojikumi-line-end">。</span>此时<span class="mojikumi-line-end">，</span>需要再丢弃 assumption 3<span class="mojikumi-line-end">，</span>来允许 scheduler <i>preempt</i> 一个 job 而 schedule 到另一个<span class="mojikumi-line-start">（</span>不这样做的 scheduler 被称作 <i>non-preemptive</i> scheduler<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>然后就可以采用 STCF (shortest time-to-completion first / PSJF, preemptive shortest job first) 达到最优解<span class="mojikumi-line-end">：</span>在新 job arrive 时<span class="mojikumi-line-end">，</span>如果它的总用时比当前 job 的剩余用时还短<span class="mojikumi-line-end">，</span>可以 schedule 到新 job<span class="mojikumi-line-end">。</span></p>
<h3 id="response-time" class="heading"><a href="#response-time" class="heading-anchor" aria-label="章节： Response Time" tabindex="-1"></a><span>Response Time</span></h3>
<p>为了让用户在交互中获得更好的体验<span class="mojikumi-line-end">，</span>turnaround time 是不够的<span class="mojikumi-line-end">，</span>还需要引入新的 metric<span class="mojikumi-line-end">，</span><i>response time</i><span class="mojikumi-line-end">，</span>它可以用一个 job 从 arrival 到 first run 的用时衡量<span class="mojikumi-line-end">。</span></p>
<p>上面提到的各种 scheduling policy<span class="mojikumi-line-end">，</span>例如 STCF<span class="mojikumi-line-end">，</span>response time 都很差<span class="mojikumi-line-end">，</span>被排到后面运行的 job 需要等待很久<span class="mojikumi-line-end">。</span></p>
<p>Round-Robin (RR) policy 会让每个 job 运行一个 <i>time slice</i> (<i>scheduling quantum</i>)<span class="mojikumi-line-end">，</span>然后切换到下一个 job<span class="mojikumi-line-end">，</span>所以 RR 也被称作 <i>time-slicing</i><span class="mojikumi-line-end">。</span>time slice 越小 response time 也就越小<span class="mojikumi-line-end">，</span>但如果 time slice 过小<span class="mojikumi-line-end">，</span>context switching<span class="mojikumi-line-start">（</span>包括存储/恢复 register<span class="mojikumi-line-end">，</span>以及 cache miss penalty<span class="mojikumi-line-end">）</span>在用时中的占比就会过大<span class="mojikumi-line-end">，</span>从而显著影响性能<span class="mojikumi-line-end">，</span>所以需要一定大小的 time slice 来 <i>amortize</i> 掉 context switching cost<span class="mojikumi-line-end">。</span>RR 的 response time 较小<span class="mojikumi-line-end">，</span>但 turnaround time 很大<span class="mojikumi-line-end">，</span>比 FIFO 还大<span class="mojikumi-line-end">。</span></p>
<p>一般来说<span class="mojikumi-line-end">，</span>如果一个 policy 是 <i>fair</i> 的<span class="mojikumi-line-end">，</span>均等地将 CPU 分配给各个 job<span class="mojikumi-line-end">，</span>就会有较差的 turnaround time 和较好的 response time<span class="mojikumi-line-end">；</span>如果一个 policy unfair<span class="mojikumi-line-end">，</span>就可以有较好的 turnaround time<span class="mojikumi-line-end">，</span>但 response time 会较大<span class="mojikumi-line-end">。</span>这是一个固有的 trade-off<span class="mojikumi-line-end">：</span>鱼与熊掌<span class="mojikumi-line-end">，</span>不可兼得<span class="mojikumi-line-end">。</span><sup><a href="#user-content-fn-cake" id="user-content-fnref-cake" data-footnote-ref aria-describedby="footnote-label">1</a></sup></p>
<h3 id="incorporating-io" class="heading"><a href="#incorporating-io" class="heading-anchor" aria-label="章节： Incorporating I/O" tabindex="-1"></a><span>Incorporating I/O</span></h3>
<p>如果进一步丢弃 assumption 4<span class="mojikumi-line-end">，</span>即允许 job 进行 I/O<span class="mojikumi-line-end">，</span>则需要处理 blocked 的情况<span class="mojikumi-line-end">。</span></p>
<p>一般来说<span class="mojikumi-line-end">，</span>可以将一个 job 视作被 I/O 分割成的多个 sub-job<span class="mojikumi-line-end">，</span>然后按照之前的 policy 进行 schedule<span class="mojikumi-line-end">。</span>例如<span class="mojikumi-line-end">，</span>使用 STCF 时<span class="mojikumi-line-end">，</span>在 sub-job 的视角下<span class="mojikumi-line-end">，</span>会优先运行 I/O 密集的 job<span class="mojikumi-line-end">，</span>这可以达成 <i>overlap</i><span class="mojikumi-line-end">，</span>让 CPU 和 I/O 同时工作<span class="mojikumi-line-end">，</span>更加充分地利用系统资源<span class="mojikumi-line-end">。</span></p>
<h2 id="scheduling-the-multi-level-feedback-queue" class="heading"><a href="#scheduling-the-multi-level-feedback-queue" class="heading-anchor" aria-label="章节： Scheduling: The Multi-Level Feedback Queue" tabindex="-1"></a><span>Scheduling: The Multi-Level Feedback Queue</span></h2>
<p>之前这些简单的 scheduling policy 面临两大问题<span class="mojikumi-line-end">，</span>一是 turnaround time 和 response time 之间的矛盾<span class="mojikumi-line-end">，</span>二是 SJF/STCF 对 perfect knowledge<span class="mojikumi-line-start">（</span>assumption 5<span class="mojikumi-line-end">）</span>的依赖<span class="mojikumi-line-end">。</span></p>
<p>Multi-level Feed-back Queue (MLFQ) 是目前被广泛使用的一种 scheduling policy<span class="mojikumi-line-end">，</span>同时解决了这两大问题<span class="mojikumi-line-end">。</span></p>
<h3 id="basic-rules" class="heading"><a href="#basic-rules" class="heading-anchor" aria-label="章节： Basic Rules" tabindex="-1"></a><span>Basic Rules</span></h3>
<p>MLFQ 的基本思路是<span class="mojikumi-line-end">，</span>workload 可以分为两类<span class="mojikumi-line-end">，</span>一类是 short-running interactive job<span class="mojikumi-line-start">（</span>被 I/O 切成了小块<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>一类是 long-running CPU-intensive job<span class="mojikumi-line-end">。</span>interactive job 更需要优先运行<span class="mojikumi-line-end">，</span>这既是 SJF/STCF 的基本思想<span class="mojikumi-line-end">，</span>同时也是因为 interactive job 对 response time 的要求更高<span class="mojikumi-line-end">。</span></p>
<p>MLFQ 的基本运行规则为<span class="mojikumi-line-end">：</span>有多个不同 priority 的 job queue<span class="mojikumi-line-end">，</span>每次会选择 priority 最高的 queue<span class="mojikumi-line-end">，</span>在同一个 queue 内使用 RR<span class="mojikumi-line-end">。</span></p>
<p>理想情况下<span class="mojikumi-line-end">，</span>interactive job 的 priority 会更高<span class="mojikumi-line-end">，</span>从而逼近 STCF<span class="mojikumi-line-end">。</span></p>
<h3 id="priority-adjustment" class="heading"><a href="#priority-adjustment" class="heading-anchor" aria-label="章节： Priority Adjustment" tabindex="-1"></a><span>Priority Adjustment</span></h3>
<p>因为 scheduler 无法预先知道 job 的类型<span class="mojikumi-line-end">，</span>priority 是根据程序的运行情况动态设置的<span class="mojikumi-line-end">。</span></p>
<p>job arrive 时会先放在 priority 最高的 queue<span class="mojikumi-line-end">，</span>如果运行太久就会降低 priority<span class="mojikumi-line-end">。</span>具体来说<span class="mojikumi-line-end">，</span>一个 job 在每一级 queue 会获得一段 <i>time allotment</i><span class="mojikumi-line-end">，</span>在这一级 queue 的累计运行时长如果超过 allotment 就会降低 priority 到下一级 queue<span class="mojikumi-line-end">。</span></p>
<p>在这样的机制下<span class="mojikumi-line-end">，</span>会有两个问题<span class="mojikumi-line-end">：</span></p>
<ul>
<li>CPU 可能被几个 interactive job 占满<span class="mojikumi-line-end">，</span>导致 priority 低的 long-running job 一点 CPU 都拿不到<span class="mojikumi-line-start">（</span>这被称作 <i>starvation</i><span class="mojikumi">）</span><span class="mojikumi-line-end">。</span></li>
<li>一个 job 的行为可能随时间变化<span class="mojikumi-line-end">，</span>如果经过一段 CPU-intensive 后 priority 到了最低<span class="mojikumi-line-end">，</span>然后变为 interactive<span class="mojikumi-line-end">，</span>priority 无法恢复<span class="mojikumi-line-end">。</span></li>
</ul>
<p>为了解决这两个问题<span class="mojikumi-line-end">，</span>可以每隔一段时间进行 <i>priority boost</i><span class="mojikumi-line-end">，</span>将所有 job 的 priority 设为最高<span class="mojikumi-line-end">。</span></p>
<a id="game-the-scheduler" name="game-the-scheduler" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-blue-1 dark:bg-blue-9 b-blue" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h4 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-pencil text-blue" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Note: </span><span data-v-a2ab257f>Game the scheduler</span></h4><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>如果 allotment 不是计算累计用时<span class="mojikumi-line-end">，</span>而是每次运行时单独判断这次有没有到一个 threshold<span class="mojikumi-line-end">，</span>没达到就不降低甚至提高 priority<span class="mojikumi-line-end">，</span>是否可以达到同样的效果<span class="mojikumi-line-end">，</span>甚至自动检测到 long-running 转变为 short-running 而提升 priority？</p><p>答案是<span class="mojikumi-line-end">，</span>这样会允许一个 program 恶意地 <i>game the scheduler</i><span class="mojikumi-line-end">，</span>每次都恰好在 threshold 之前一点点执行 I/O<span class="mojikumi-line-end">，</span>从而在长时间占用 CPU 的同时维持最高的 priority<span class="mojikumi-line-end">，</span>最终达到接近独占 CPU 的效果<span class="mojikumi-line-end">。</span>这在多个用户共享 CPU 时<span class="mojikumi-line-start">（</span>例如在云服务器上<span class="mojikumi-line-end">）</span>可能造成安全问题<span class="mojikumi-line-end">。</span></p></div></div></aside>
<h3 id="tuning-mlfq" class="heading"><a href="#tuning-mlfq" class="heading-anchor" aria-label="章节： Tuning MLFQ" tabindex="-1"></a><span>Tuning MLFQ</span></h3>
<p>MLFQ 有很多可以设置的参数<span class="mojikumi-line-end">：</span>queue (level) 的数量<span class="mojikumi-line-end">，</span>每个 level 的 time slice 和 allotment<span class="mojikumi-line-end">，</span>多久进行一次 priority boost<span class="mojikumi-line-end">。</span>一般来说<span class="mojikumi-line-end">，</span>priority 越高<span class="mojikumi-line-end">，</span>time slice 和 allotment 越短<span class="mojikumi-line-end">。</span></p>
<p>MLFQ 不一定真的要实现为多个 queue<span class="mojikumi-line-end">，</span>也可以统计每个 job 的 CPU usage<span class="mojikumi-line-end">，</span>根据 usage 计算出 priority<span class="mojikumi-line-end">，</span>而让 usage 随时间 <i>decay</i> 来代替 priority boost<span class="mojikumi-line-end">，</span>这称作 <i>decay-usage</i> scheduling<span class="mojikumi-line-end">。</span></p>
<p>priority 不一定要完全基于 feedback<span class="mojikumi-line-end">，</span>也可以参考由用户提供的 <i>advice</i><span class="mojikumi-line-end">，</span>例如使用 <code>nice</code> 命令可以设置 <i>niceness</i> 来影响 job priority<span class="mojikumi-line-end">。</span></p>
<h2 id="scheduling-proportional-share" class="heading"><a href="#scheduling-proportional-share" class="heading-anchor" aria-label="章节： Scheduling: Proportional Share" tabindex="-1"></a><span>Scheduling: Proportional Share</span></h2>
<p>这章讨论的是一种不同的 scheduler<span class="mojikumi-line-end">，</span>它的主要目标是按一定的比例将 CPU 分配给各个 job<span class="mojikumi-line-end">。</span>例如<span class="mojikumi-line-end">，</span>在 virtualized data center / cloud 中<span class="mojikumi-line-end">，</span>可以将 CPU 均等地分配给各个用户<span class="mojikumi-line-end">。</span></p>
<h3 id="lottery-scheduling" class="heading"><a href="#lottery-scheduling" class="heading-anchor" aria-label="章节： Lottery Scheduling" tabindex="-1"></a><span>Lottery Scheduling</span></h3>
<p>在 <i>lottery scheduling</i> 中<span class="mojikumi-line-end">，</span>每个 job 被分配了一定数量的 <i>ticket</i><span class="mojikumi-line-end">，</span>每个 time slice 结束时随机选择一个 winning ticket<span class="mojikumi-line-end">，</span>schedule 到对应的 job<span class="mojikumi-line-end">，</span>时间久了之后会趋近于按 ticket 数量的 CPU 分配<span class="mojikumi-line-end">。</span></p>
<p>lottery scheduling 还会提供一些 ticket mechanism<span class="mojikumi-line-end">：</span></p>
<ul>
<li>可以给每个 user 一些 ticket<span class="mojikumi-line-end">，</span>每个 user 再将 ticket 分给各个 job<span class="mojikumi-line-end">。</span></li>
<li>一个 job 可以将自己的 ticket transfer 给其他 job<span class="mojikumi-line-end">。</span></li>
<li>如果各个 job 之间互相信任<span class="mojikumi-line-end">，</span>可以进行 ticket inflation<span class="mojikumi-line-end">，</span>一个 job 需要更多 CPU 时直接给自己更多 ticket 即可<span class="mojikumi-line-end">，</span>不需要和其他 job 沟通<span class="mojikumi-line-end">。</span></li>
</ul>
<h3 id="stride-scheduling" class="heading"><a href="#stride-scheduling" class="heading-anchor" aria-label="章节： Stride Scheduling" tabindex="-1"></a><span>Stride Scheduling</span></h3>
<p>stride scheduling 不依赖于随机<span class="mojikumi-line-end">，</span>可以确定性地达到设定的比例<span class="mojikumi-line-end">。</span></p>
<p>用一个大数除以每个 job 的 ticket value 得到每个 job 的 <i>stride</i><span class="mojikumi-line-end">，</span>对每个 job 维护一个 <i>pass</i><span class="mojikumi-line-end">，</span>每次运行一个 job 后将 pass 加上 stride<span class="mojikumi-line-end">，</span>schedule 到 pass 最低的 job<span class="mojikumi-line-end">。</span>每个循环内都会精确地达到设定的比例<span class="mojikumi-line-end">。</span></p>
<p>stride scheduling 的一个劣势是新加入的 job 的 pass 不好设定<span class="mojikumi-line-end">，</span>而 lottery scheduling 不需要维护状态<span class="mojikumi-line-end">，</span>可以轻松地添加新的 job<span class="mojikumi-line-end">。</span></p>
<h3 id="the-linux-completely-fair-scheduler-cfs" class="heading"><a href="#the-linux-completely-fair-scheduler-cfs" class="heading-anchor" aria-label="章节： The Linux Completely Fair Scheduler (CFS)" tabindex="-1"></a><span>The Linux Completely Fair Scheduler (CFS)</span></h3>
<p>Linux 的 Completely Fair Scheduler (CFS) 高效而 scalable 地实现了 fair-share scheduling<span class="mojikumi-line-end">。</span></p>
<p>CFS 会记录每个 job 的 <i>virtual runtime</i> (<code>vruntime</code>)<span class="mojikumi-line-end">，</span>每次运行后加上这次运行的时长<span class="mojikumi-line-end">，</span>schedule 到 <code>vruntime</code> 最低的 job<span class="mojikumi-line-end">。</span>time slice 是不固定的<span class="mojikumi-line-end">，</span>由 <code>sched_<wbr>latency</code> 除以 job 数量决定<span class="mojikumi-line-end">，</span>并会与 <code>min_<wbr>granularity</code> 取较大值<span class="mojikumi-line-end">，</span>防止 time slice 过小导致 context switching 过多<span class="mojikumi-line-end">。</span>time slice 可能不是 timer interrupt 的整数倍<span class="mojikumi-line-end">，</span>但 <code>vruntime</code> 会精确记录实际用时<span class="mojikumi-line-end">。</span></p>
<p>可以通过设置 <code>niceness</code> 调整一个 job 的 <code>weight</code><span class="mojikumi-line-end">，</span><code>niceness</code> 越低 <code>weight</code> 越高<span class="mojikumi-line-end">，</span>呈指数降低的关系<span class="mojikumi-line-end">。</span>设置了 <code>niceness</code> 后<span class="mojikumi-line-end">，</span>time slice 会按照 <code>weight</code> 分配<span class="mojikumi-line-end">，</span>而 <code>vruntime</code> 每次增加的值会再调整回来<span class="mojikumi-line-end">，</span>即 <code>weight</code> 大的会获得更大的 time slice 而增长同样多的 <code>vruntime</code><span class="mojikumi-line-end">。</span></p>
<p>CFS 使用 red-black tree 维护各个 job 的 <code>vruntime</code> 以快速取出最小值<span class="mojikumi-line-end">。</span>一个 job blocked 时会从树上移除<span class="mojikumi-line-end">，</span>而再插入到树上时其 <code>vruntime</code> 会设为此时树上的最小值<span class="mojikumi-line-end">，</span>以避免一个长期 blocked 的 job 恢复后独占 CPU<span class="mojikumi-line-end">，</span>但这样会导致 I/O 频繁或长期 sleep 的 job 实际上没有拿到 fair share<span class="mojikumi-line-end">。</span></p>
<p>作为一个得到了广泛实际应用的 scheduler<span class="mojikumi-line-end">，</span>CFS 还有很多其他 feature<span class="mojikumi-line-end">，</span>例如通过一些手段优化了 cache performance<span class="mojikumi-line-end">，</span>可以高效处理有多个 CPU 的情形<span class="mojikumi-line-end">，</span>可以将多个 process 视作一个 group 而不是对每单个 process 进行 schedule<span class="mojikumi-line-end">。</span></p>
<h2 id="multiprocessor-scheduling" class="heading"><a href="#multiprocessor-scheduling" class="heading-anchor" aria-label="章节： Multiprocessor Scheduling" tabindex="-1"></a><span>Multiprocessor Scheduling</span></h2>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-gray-2 dark:bg-gray-11 b-gray-6" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-timer-sand text-gray" data-v-a2ab257f></span><!--v-if--><span data-v-a2ab257f>WIP</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><blockquote>
<p>As this topic is relatively advanced, it may be best to cover it after you have studied the topic of concurrency in some detail (i.e., the second major <span class="mojikumi">“</span>easy piece<span class="mojikumi">”</span> of the book).</p>
</blockquote></div></div></aside>
<h2 id="the-abstraction-address-spaces" class="heading"><a href="#the-abstraction-address-spaces" class="heading-anchor" aria-label="章节： The Abstraction: Address Spaces" tabindex="-1"></a><span>The Abstraction: Address Spaces</span></h2>
<p>为了支持 time sharing<span class="mojikumi-line-end">，</span>需要在 physical memory 中同时存放多个 process 的 memory<span class="mojikumi-line-end">。</span>为了便于使用<span class="mojikumi-line-end">，</span>OS 需要将 physical memory virtualize<span class="mojikumi-line-end">，</span>提供称作 <i>address space</i> 的 abstraction<span class="mojikumi-line-end">。</span></p>
<p>一个 process 的 address space 包括 code<span class="mojikumi-line-end">、</span>stack<span class="mojikumi-line-end">、</span>heap<span class="mojikumi-line-end">、</span>data 等部分<span class="mojikumi-line-end">，</span>各个部分一般有较为固定的 layout<span class="mojikumi-line-end">，</span>但其对应的 physical memory address 是不固定的<span class="mojikumi-line-end">。</span></p>
<p>virtual memory (VM) 需要达到若干个目标<span class="mojikumi-line-end">：</span></p>
<ul>
<li>transparency: process 感受不到 VM 的存在<span class="mojikumi-line-end">，</span>像是独占了整个巨大的 physical memory<span class="mojikumi-line-end">。</span></li>
<li>efficiency: time 和 space 两方面的 overhead 都不能太大<span class="mojikumi-line-end">，</span>需要 hardware 的配合<span class="mojikumi-line-end">。</span></li>
<li>protection / isolation: 每个 process 只能访问自己的 address space<span class="mojikumi-line-end">，</span>不能访问其他 process 或者 OS 自身的 memory<span class="mojikumi-line-end">。</span></li>
</ul>
<p>user-level program 使用的所有 address 都是 virtual address<span class="mojikumi-line-end">，</span>只有 OS<span class="mojikumi-line-start">（</span>以及 hardware<span class="mojikumi-line-end">）</span>能接触到 physical address<span class="mojikumi-line-end">。</span></p>
<h2 id="interlude-memory-api" class="heading"><a href="#interlude-memory-api" class="heading-anchor" aria-label="章节： Interlude: Memory API" tabindex="-1"></a><span>Interlude: Memory API</span></h2>
<p>C program 可以使用 stack memory 或 heap memory<span class="mojikumi-line-end">。</span></p>
<p>stack memory 的 allocation 和 deallocation 都是 implicit 的<span class="mojikumi-line-end">，</span>又称作 <i>automatic</i> memory<span class="mojikumi-line-end">。</span></p>
<p>heap memory 需要使用 <code>malloc()</code> allocate<span class="mojikumi-line-end">，</span>使用 <code>free()</code> deallocate<span class="mojikumi-line-end">，</span>例如<span class="mojikumi-line-end">：</span></p>
<ul>
<li><code>double<wbr> *<wbr>d<wbr> = <wbr>malloc<wbr>(<wbr>sizeof<wbr>(*<wbr>d<wbr>))</code></li>
<li><code>int<wbr> *<wbr>x<wbr> = <wbr>malloc<wbr>(<wbr>sizeof<wbr>(*<wbr>x<wbr>) * <wbr>10<wbr>)</code></li>
<li><code>char<wbr> *<wbr>s<wbr> = <wbr>malloc<wbr>(<wbr>strlen<wbr>(<wbr>buf<wbr>) + <wbr>1<wbr>)</code></li>
<li><code>free(x)</code></li>
</ul>
<p>heap memory 的使用很容易出错<span class="mojikumi-line-end">，</span>例如<span class="mojikumi-line-end">：</span></p>
<dl>
<dt>null pointer dereference</dt>
<dd>使用前没有 allocate
</dd>
<dt>uninitialized read</dt>
<dd>没有初始化内容就读取<span class="mojikumi-line-start">（</span>以为内容会是 0<span class="mojikumi-line-end">）</span>
</dd>
<dt>buffer overflow</dt>
<dd>allocate 的 memory 不够大<span class="mojikumi-line-end">，</span>例如字符串没有在长度的基础上加一
</dd>
<dt>memory leak</dt>
<dd>long-running program 的 heap memory 使用完毕后没有 free
</dd>
<dt>use after free</dt>
<dd>在 free 之后继续使用 <i>dangling pointer</i>
</dd>
<dt>double free</dt>
<dd>free 之后再次 free
</dd>
</dl>
<a id="tip-if-it-compiles-it-works" name="tip-if-it-compiles-it-works" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><details class="shadow-md rd-1 b-l-6 my-6 bg-blue-1 dark:bg-blue-9 b-blue" data-v-a2ab257f><summary class="p-3 flex justify-between items-center cursor-pointer" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-info-circle-outline text-blue" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Info: </span><span data-v-a2ab257f>Tip: if it compiles it works</span></h3><span class="details-icon text-5" data-v-a2ab257f></span></summary><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><blockquote>
<p>Just because a program compiled(!) or even ran once or many times correctly does not mean the program is correct.</p>
</blockquote><blockquote>
<p>Get to work and debug it before you blame those other components.</p>
</blockquote><p><s>这边建议您用 Rust<span class="mojikumi-line-start">（</span></s></p></div></details></aside>
<p><code>malloc()</code> 和 <code>free()</code> 不是 system call<span class="mojikumi-line-end">，</span>而是 library call<span class="mojikumi-line-end">。</span>malloc library 使用 system call <code>brk()</code>/<code>sbrk()</code> 设置 program 的 <i>break</i><span class="mojikumi-line-start">（</span>heap 末尾的 address<span class="mojikumi-line-end">）</span>来获取 memory<span class="mojikumi-line-end">，</span>进而分配给用户<span class="mojikumi-line-end">。</span></p>
<p>另外还有 <code>calloc</code> 可以用来初始化 malloc 得到的 memory<span class="mojikumi-line-end">，</span><code>realloc</code> 可以用来调整一块已分配的 heap memory 的大小<span class="mojikumi-line-end">。</span></p>
<p>可以用 <code>mmap</code> 进行 memory mapping<span class="mojikumi-line-end">，</span>例如可以 map 到 anonymous file 来获取一块 memory<span class="mojikumi-line-end">。</span></p>
<h2 id="mechanism-address-translation" class="heading"><a href="#mechanism-address-translation" class="heading-anchor" aria-label="章节： Mechanism: Address Translation" tabindex="-1"></a><span>Mechanism: Address Translation</span></h2>
<p>为了高效且灵活地 virtualize memory<span class="mojikumi-line-end">，</span>基本思想是 <i>(hardware-based) address translation</i><span class="mojikumi-line-end">，</span>将 memory access 从 virtual address 翻译为 physical address<span class="mojikumi-line-end">。</span>OS 会管理 memory<span class="mojikumi-line-end">，</span>配置 hardware<span class="mojikumi-line-end">，</span>最终由 hardware 高效地进行 address translation<span class="mojikumi-line-end">。</span></p>
<p>我们先做一些简化<span class="mojikumi-line-end">，</span>假设<span class="mojikumi-line-end">：</span></p>
<ul>
<li>每个 process 的 address space 都映射到了 physical memory 中连续的<sup><a href="#user-content-fn-contiguous" id="user-content-fnref-contiguous" data-footnote-ref aria-describedby="footnote-label">2</a></sup>一段</li>
<li>各个 process 的 address space size 相同</li>
<li>physical memory 足够大<span class="mojikumi-line-end">，</span>能装下所有 process 的 address space</li>
</ul>
<a id="software-based-relocation" name="software-based-relocation" aria-hidden="true"></a>
<aside role="note" data-v-a2ab257f><div class="shadow-md rd-1 b-l-6 my-6 bg-blue-1 dark:bg-blue-9 b-blue" data-v-a2ab257f><div class="p-3 flex justify-between items-center" data-v-a2ab257f><h3 class="flex items-center gap-1 font-bold" data-v-a2ab257f><span class="text-5 i-mdi-pencil text-blue" data-v-a2ab257f></span><span class="sr-only" data-v-a2ab257f>Note: </span><span data-v-a2ab257f>Software-based Relocation</span></h3><!--v-if--></div><div class="overflow-auto rd-br-1 bg-card px-6 dark:bg-bghover" data-v-a2ab257f><p>在早期还没有 hardware support 时<span class="mojikumi-line-end">，</span>有的系统使用了一种 software-based relocation<span class="mojikumi-line-end">，</span>其原理是在 load program 时进行 address translation<span class="mojikumi-line-end">。</span></p><p>这样做不能提供 protection<span class="mojikumi-line-start">（</span>没有限制可以访问的 address<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>而且很难再次 relocate<span class="mojikumi-line-start">（</span>移动 address space 对应的 physical memory<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>所以后来被抛弃了<span class="mojikumi-line-end">。</span></p></div></div></aside>
<h3 id="base-and-bounds" class="heading"><a href="#base-and-bounds" class="heading-anchor" aria-label="章节： Base and Bounds" tabindex="-1"></a><span>Base and Bounds</span></h3>
<p>在 1950<span class="mojikumi-narrow-left">’</span>s<span class="mojikumi-line-end">，</span>当时的计算机使用了被称作 <i>base and bounds</i><sup><a href="#user-content-fn-bounds" id="user-content-fnref-bounds" data-footnote-ref aria-describedby="footnote-label">3</a></sup> / <i>dynamic relocation</i> 的技术实现简单高效且能提供 protection 的 VM<span class="mojikumi-line-end">。</span></p>
<p>CPU 中添加两个 register<span class="mojikumi-line-end">，</span><i>base</i> 和 <i>bounds</i><span class="mojikumi-line-end">。</span>base 即 virtual address 0 对应的 physical address<span class="mojikumi-line-end">，</span>在 access memory 时进行 address translation<span class="mojikumi-line-end">，</span>用 base 加上 virtual address 计算 physical address<span class="mojikumi-line-end">。</span>bounds 是 address space 的大小<span class="mojikumi-line-end">，</span>会检查 virtual address 不超过 bounds<span class="mojikumi-line-end">。</span></p>
<h3 id="hardware-support" class="heading"><a href="#hardware-support" class="heading-anchor" aria-label="章节： Hardware Support" tabindex="-1"></a><span>Hardware Support</span></h3>
<p>为了实现 base and bounds<span class="mojikumi-line-end">，</span>需要若干 hardware support<span class="mojikumi-line-end">：</span></p>
<ul>
<li>支持 kernel mode 和 user mode<span class="mojikumi-line-end">。</span></li>
<li>在 <i>memory management unit</i> (MMU) 中提供 base register 和 bounds register<span class="mojikumi-line-end">。</span></li>
<li>提供特殊的 privileged instruction 来修改 base 和 bounds<span class="mojikumi-line-end">，</span>只有 OS 能修改它们<span class="mojikumi-line-end">，</span>否则一个 user process 将可以 wreak havoc<sup><a href="#user-content-fn-wreak" id="user-content-fnref-wreak" data-footnote-ref aria-describedby="footnote-label">4</a></sup><span class="mojikumi-line-end">。</span></li>
<li>在 memory access 超出 bounds 时 generate exception<span class="mojikumi-line-end">，</span>调用 exception handler<span class="mojikumi-line-end">。</span></li>
</ul>
<h3 id="operating-system-issues" class="heading"><a href="#operating-system-issues" class="heading-anchor" aria-label="章节： Operating System Issues" tabindex="-1"></a><span>Operating System Issues</span></h3>
<p>OS 需要做的工作有<span class="mojikumi-line-end">：</span></p>
<ul>
<li>在 create process 时为其分配 memory<span class="mojikumi-line-end">。</span></li>
<li>在 terminate process 时回收 memory<span class="mojikumi-line-end">。</span></li>
<li>在 context switch 时存储<span class="mojikumi-line-end">、</span>设置 base 和 bounds<span class="mojikumi-line-end">。</span>此时可以进行 relocate<span class="mojikumi-line-end">：</span>将 base 修改为与上次 schedule 到这个 process 时不同的位置<span class="mojikumi-line-end">，</span>并将数据复制过去<span class="mojikumi-line-end">。</span></li>
<li>提供 out-of-bounds memory access 的 exception handler<span class="mojikumi-line-end">，</span>一般会 kill 掉这个 process<span class="mojikumi-line-end">。</span></li>
</ul>
<p>在我们简单的假设下<span class="mojikumi-line-end">，</span>可以使用一个 <i>free list</i> 维护空闲的 memory slots<span class="mojikumi-line-end">。</span></p>
<h2 id="segmentation" class="heading"><a href="#segmentation" class="heading-anchor" aria-label="章节： Segmentation" tabindex="-1"></a><span>Segmentation</span></h2>
<p>在 Base and Bounds 中<span class="mojikumi-line-end">，</span>heap 和 stack 之间的空位一般不会用满<span class="mojikumi-line-end">，</span>但没有使用的空间也会占用 physical memory<span class="mojikumi-line-end">，</span>这会造成严重的浪费<span class="mojikumi-line-start">（</span><i>internal fragmentation</i><span class="mojikumi">）</span><span class="mojikumi-line-end">。</span>并且<span class="mojikumi-line-end">，</span>Base and Bounds 不支持运行 address space 比 physical memory 大的 program<span class="mojikumi-line-end">。</span>所以我们需要更灵活高效的机制来支持 large address space<span class="mojikumi-line-end">。</span></p>
<p>我们可以使用 <i>segmentation</i><span class="mojikumi-line-end">，</span>将 memory space 划分成多个 <i>segment</i><span class="mojikumi-line-end">，</span>例如 code<span class="mojikumi-line-end">、</span>stack 和 heap<span class="mojikumi-line-end">，</span>每个 segment 是连续的<span class="mojikumi-line-end">，</span>但整体不必连续<span class="mojikumi-line-end">，</span>从而可以更加灵活地进行分配<span class="mojikumi-line-end">，</span>减少 internal fragmentation<span class="mojikumi-line-end">。</span></p>
<h3 id="hardware-support-2" class="heading"><a href="#hardware-support-2" class="heading-anchor" aria-label="章节： Hardware Support" tabindex="-1"></a><span>Hardware Support</span></h3>
<p>为了支持 segmentation<span class="mojikumi-line-end">，</span>需要将整体的一对 base and bounds register 变成每个 segment 各一对<span class="mojikumi-line-end">。</span></p>
<p>在进行 address translation 时<span class="mojikumi-line-end">，</span>需要先识别一个 address 属于哪个 segment<span class="mojikumi-line-end">。</span>explicit approach 通过 address 的最高几位作为 segment 标识<span class="mojikumi-line-end">，</span>而 implicit approach 通过地址的生成方式<span class="mojikumi-line-start">（</span>是否来自 PC / stack pointer<span class="mojikumi-line-end">）</span>判断 segment<span class="mojikumi-line-end">。</span></p>
<p>stack 是 grow backwards 的<span class="mojikumi-line-end">，</span>需要特殊支持<span class="mojikumi-line-end">。</span>可以在 hardware 中添加表示 grow 方向的 flag bit<span class="mojikumi-line-end">，</span>对于 grow backwards 的 segment<span class="mojikumi-line-end">，</span>其 base 是这段 address 的上界<span class="mojikumi-line-end">，</span>offset 是负数<span class="mojikumi-line-end">，</span>越界判断也有所不同<span class="mojikumi-line-end">。</span></p>
<p>为了支持 shared memory<span class="mojikumi-line-end">，</span>尤其是 code sharing<span class="mojikumi-line-end">，</span>需要添加 protection bits<span class="mojikumi-line-end">，</span>表示一个 segment 是否可以 read / write / execute<span class="mojikumi-line-end">。</span>进行 code sharing 时<span class="mojikumi-line-end">，</span>可以将权限设为 read-execute<span class="mojikumi-line-end">，</span>禁止修改<span class="mojikumi-line-end">，</span>从而既能 share 又能 isolate<span class="mojikumi-line-end">。</span>这也能避免 stack / heap 被执行<span class="mojikumi-line-end">，</span>一定程度上避免一些攻击<span class="mojikumi-line-end">。</span></p>
<p>只分成 code<span class="mojikumi-line-end">、</span>stack<span class="mojikumi-line-end">、</span>heap 等少量几个 segment 被称作 <i>coarse-grained</i> segmentation<span class="mojikumi-line-end">。</span>有的系统支持成百上千个 segment<span class="mojikumi-line-end">，</span>称作 <i>fine-grained</i> segmentation<span class="mojikumi-line-end">，</span>这需要存储 <i>segment table</i><span class="mojikumi-line-end">。</span></p>
<h3 id="os-support" class="heading"><a href="#os-support" class="heading-anchor" aria-label="章节： OS Support" tabindex="-1"></a><span>OS Support</span></h3>
<p>为了支持 segmentation<span class="mojikumi-line-end">，</span>OS 需要做的事情有<span class="mojikumi-line-end">：</span></p>
<ul>
<li>在 context switch 时存储<span class="mojikumi-line-end">、</span>切换 segment registers</li>
<li>管理 physical memory 的 free space<span class="mojikumi-line-end">，</span>从而支持<span class="mojikumi-line-end">：</span>
<ul>
<li>创建新的 address space</li>
<li>segment grow<span class="mojikumi-line-end">，</span>例如 <code>sbrk()</code></li>
</ul>
</li>
</ul>
<p>由于 segment 的 size 是不固定的<span class="mojikumi-line-end">，</span>physical memory 中各个 segment 之间可能会出现很多空洞<span class="mojikumi-line-end">，</span>这被称作 <i>external fragmentation</i><span class="mojikumi-line-end">，</span>导致 free space management 非常困难<span class="mojikumi-line-end">。</span></p>
<p>一种解决方式是进行 <i>compact</i><span class="mojikumi-line-end">，</span>通过挪移 segment 来消除 external fragmentation<span class="mojikumi-line-end">，</span>但这需要频繁移动大量数据<span class="mojikumi-line-end">，</span>非常 expensive<span class="mojikumi-line-end">，</span>效率很低<span class="mojikumi-line-end">。</span>所以<span class="mojikumi-line-end">，</span>一般不会进行 compact<span class="mojikumi-line-end">，</span>而是会使用其他方式尽量减少 internal fragmentation<span class="mojikumi-line-end">。</span></p>
<h2 id="free-space-management" class="heading"><a href="#free-space-management" class="heading-anchor" aria-label="章节： Free-Space Management" tabindex="-1"></a><span>Free-Space Management</span></h2>
<p>如果 memory 被分成了 fixed-size units<span class="mojikumi-line-end">，</span>以 unit 为分配的基本单位<span class="mojikumi-line-end">，</span>则 free-space management 会比较容易<span class="mojikumi-line-end">。</span>如果分配出的每一块 memory 大小各异<span class="mojikumi-line-end">，</span>则容易造成 external fragmentation<span class="mojikumi-line-end">，</span>需要一些机制来优化<span class="mojikumi-line-end">。</span></p>
<p>参见 <a href="/post/2022/11/csapp-9#dynamic-memory-allocation">CS:APP 第九章 Dynamic Memory Allocation</a><span class="mojikumi-line-end">。</span></p>
<h2 id="paging-introduction" class="heading"><a href="#paging-introduction" class="heading-anchor" aria-label="章节： Paging: Introduction" tabindex="-1"></a><span>Paging: Introduction</span></h2>
<p>将 memory 分成 variable-sized pieces 会使 free-space management 比较困难<span class="mojikumi-line-end">，</span>所以<span class="mojikumi-line-end">，</span>在 virtual memory 中<span class="mojikumi-line-end">，</span>一般实际上会分成 fixed-size units<span class="mojikumi-line-end">，</span>address space 中的每个 unit 称作一个 <i>page</i><span class="mojikumi-line-end">，</span>对应的 physical memory 称作 <i>page frame</i><span class="mojikumi-line-end">，</span>这个做法称作 <i>paging</i><span class="mojikumi-line-end">。</span></p>
<p>paging 可以避免 external fragmentation<span class="mojikumi-line-end">，</span>并且更加 flexible<span class="mojikumi-line-end">，</span>可以支持 sparse address space<span class="mojikumi-line-end">，</span>也不需要对 program 如何使用 address space 进行假定<span class="mojikumi-line-end">，</span>例如不需要对 stack 的 grow 方向进行特殊处理<span class="mojikumi-line-end">。</span></p>
<p><i>page table</i> 用来记录 virtual page 和 physical frame 的对应关系<span class="mojikumi-line-end">，</span>用于 address translation<span class="mojikumi-line-end">。</span>每个 process 都各有自己的 page table<span class="mojikumi-line-end">，</span>context switch 时需要切换 page table<span class="mojikumi-line-end">。</span></p>
<p>在进行 address translation 时<span class="mojikumi-line-end">，</span>需要将 address 分成 <i>virtual page number</i> (VPN) 和 <i>offset</i> 两部分<span class="mojikumi-line-end">，</span>其中 offset 位于低位<span class="mojikumi-line-end">，</span>位数对应一个 page 的大小<span class="mojikumi-line-end">。</span>VPN 作为 page table 的索引来访问对应的 <i>page table entry</i> (PTE)<span class="mojikumi-line-end">，</span>从而得到 <i>physical frame number</i> (PFN, or PPN)<span class="mojikumi-line-end">，</span>再将 PFN 和 offset 拼接就可以得到最终的 physical address<span class="mojikumi-line-end">。</span></p>
<p>page table 比较大<span class="mojikumi-line-end">，</span>不像 base and bounds 可以存在专门的 hardware 里<span class="mojikumi-line-end">，</span>而是要存在 physical memory 中<span class="mojikumi-line-end">。</span></p>
<p>page table 可以使用各种数据结构存储<span class="mojikumi-line-end">，</span>最简单的是 <i>linear page table</i><span class="mojikumi-line-end">，</span>就是一个一维数组<span class="mojikumi-line-end">，</span>以 VPN 作为下标<span class="mojikumi-line-end">。</span>但无论如何<span class="mojikumi-line-end">，</span>page table 的基本数据单位是 PTE<span class="mojikumi-line-end">。</span></p>
<p>一个简化的 PTE 需要存储 PFN<span class="mojikumi-line-end">、</span>valid bit 和 protection bits<span class="mojikumi-line-end">。</span>其中<span class="mojikumi-line-end">，</span>valid bit 表示有的 page 是 invalid 的<span class="mojikumi-line-end">，</span>没有分配 physical frame<span class="mojikumi-line-end">，</span>可以节约 memory<span class="mojikumi-line-end">。</span>另外<span class="mojikumi-line-end">，</span>实际的 PTE 还会有 present bit<span class="mojikumi-line-end">、</span>dirty bit<span class="mojikumi-line-end">、</span>reference bit 用于 swapping<span class="mojikumi-line-end">。</span>根据具体实现可能还会存一些别的信息<span class="mojikumi-line-end">。</span></p>
<p>在现在这个简单的 page table 设计下<span class="mojikumi-line-end">，</span>每次 memory access 都需要访问两次 physical memory<span class="mojikumi-line-start">（</span>先访问 page table 再访问实际目标<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>而且 address space 较大时 page table 也会很大<span class="mojikumi-line-end">，</span>也就是说它的 time 和 space overhead 都很大<span class="mojikumi-line-end">，</span>需要进一步优化<span class="mojikumi-line-end">。</span></p>
<h2 id="paging-faster-translations-tlbs" class="heading"><a href="#paging-faster-translations-tlbs" class="heading-anchor" aria-label="章节： Paging: Faster Translations (TLBs)" tabindex="-1"></a><span>Paging: Faster Translations (TLBs)</span></h2>
<p>为了解决 page table 的 time overhead<span class="mojikumi-line-end">，</span>需要 hardware 的帮助<span class="mojikumi-line-end">，</span>即使用 <i>translation lookaside buffer</i> (TLB)<sup><a href="#user-content-fn-tlb" id="user-content-fnref-tlb" data-footnote-ref aria-describedby="footnote-label">5</a></sup> 来加速 page table access<span class="mojikumi-line-end">。</span></p>
<p>TLB 中存储了少量 PTE<span class="mojikumi-line-end">，</span>进行 address translation 时<span class="mojikumi-line-end">，</span>首先查找 TLB<span class="mojikumi-line-end">，</span>找到了称作 TLB hit<span class="mojikumi-line-end">，</span>否则称作 TLB miss<span class="mojikumi-line-end">，</span>需要再读取 page table<span class="mojikumi-line-end">，</span>返回结果并更新 TLB<span class="mojikumi-line-end">。</span>TLB miss 代价高昂<span class="mojikumi-line-end">，</span>需要尽可能避免<span class="mojikumi-line-end">。</span></p>
<h3 id="locality-why-is-tlb-hit-rate-high" class="heading"><a href="#locality-why-is-tlb-hit-rate-high" class="heading-anchor" aria-label="章节： Locality: Why is TLB Hit Rate High?" tabindex="-1"></a><span>Locality: Why is TLB Hit Rate High?</span></h3>
<p>TLB 利用了 program 的 <i>spatial locality</i><span class="mojikumi-line-end">，</span>即一小段时间内访问的 address 一般是邻近的<span class="mojikumi-line-end">，</span>很多 address 位于同一个 page<span class="mojikumi-line-end">，</span>从而可以 TLB hit<span class="mojikumi-line-end">；</span>也利用了 <i>temporal locality</i><span class="mojikumi-line-end">，</span>即一小段时间内同一个 address 可能被多次访问<span class="mojikumi-line-end">，</span>从而可以 TLB hit<span class="mojikumi-line-end">。</span></p>
<p>locality 是 program 的性质<span class="mojikumi-line-end">，</span>不同 program 有着不一样的 locality<span class="mojikumi-line-end">，</span>这会影响其性能<span class="mojikumi-line-end">。</span>如果 program 短时间内访问的 page 数量超过了 TLB 的容量<span class="mojikumi-line-end">，</span>就可能产生大量 TLB miss<span class="mojikumi-line-end">，</span>这称作 exceeding the <i>TLB coverage</i><span class="mojikumi-line-end">。</span>有的 program 由于其特殊性就是需要随机大范围访问 memory<span class="mojikumi-line-end">，</span>例如使用了复杂数据结构的 DBMS<span class="mojikumi-line-end">，</span>可以为它们设置更大的 page size<span class="mojikumi-line-end">，</span>来缓解这一问题<span class="mojikumi-line-end">。</span></p>
<h3 id="who-handles-the-tlb-miss" class="heading"><a href="#who-handles-the-tlb-miss" class="heading-anchor" aria-label="章节： Who Handles The TLB Miss?" tabindex="-1"></a><span>Who Handles The TLB Miss?</span></h3>
<p>TLB miss 可以由 hardware 或 software 处理<span class="mojikumi-line-end">。</span></p>
<p>在 hardware-managed TLB 中<span class="mojikumi-line-end">，</span>page table 有固定的格式<span class="mojikumi-line-end">，</span>OS 需要设置 page table base register<span class="mojikumi-line-end">，</span>由 hardware 进行 TLB miss 的处理<span class="mojikumi-line-start">（</span>page table 的访问<span class="mojikumi">）</span><span class="mojikumi-line-end">。</span></p>
<p>在 software-managed TLB 中<span class="mojikumi-line-end">，</span>TLB miss 会触发 trap<span class="mojikumi-line-end">，</span>由 OS 提供的 trap handler 进行处理<span class="mojikumi-line-end">，</span>使用特殊的 privileged instruction 修改 TLB<span class="mojikumi-line-end">。</span>这样 OS 可以灵活设计 page table<span class="mojikumi-line-end">，</span>不受 hardware 的限制<span class="mojikumi-line-end">。</span>这个 trap handler 有两点需要注意<span class="mojikumi-line-end">：</span></p>
<ul>
<li>返回到 user program 时<span class="mojikumi-line-end">，</span>要返回到触发 trap 的那条 instruction<span class="mojikumi-line-end">，</span>而非像 system call 一样返回到下一条 instruction<span class="mojikumi-line-end">。</span></li>
<li>trap handler 自身不能再触发 TLB miss<span class="mojikumi-line-end">，</span>要么 trap handler 直接访问 physical memory 绕开 TLB<span class="mojikumi-line-end">，</span>要么在 TLB 中设置一些 <i>wired</i> translation<span class="mojikumi-line-end">，</span>永久保留在 TLB 中不被清除<span class="mojikumi-line-end">。</span></li>
</ul>
<h3 id="tlb-contents-what’s-in-there" class="heading"><a href="#tlb-contents-what’s-in-there" class="heading-anchor" aria-label="章节： TLB Contents: What’s In There?" tabindex="-1"></a><span>TLB Contents: What<span class="mojikumi-narrow-left">’</span>s In There?</span></h3>
<p>TLB entry 的内容一般包括<span class="mojikumi-line-end">：</span></p>
<ul>
<li>PTE 的信息<span class="mojikumi-line-end">：</span>PFN<span class="mojikumi-line-end">、</span>protection bits<span class="mojikumi-line-end">、</span>dirty bit 等</li>
<li>VPN<span class="mojikumi-line-end">：</span>TLB 一般是 <a href="/post/2022/12/csapp-6#cache-%E7%9A%84%E5%88%86%E7%B1%BB">fully associative</a> 的<span class="mojikumi-line-end">，</span>需要存储 VPN 作为 cache tag</li>
<li>valid bit<span class="mojikumi-line-end">：</span>表示这个 TLB entry 存储的信息是否 valid<span class="mojikumi-line-end">，</span>和 page table 的 valid bit 不同</li>
<li>wired<span class="mojikumi-line-end">：</span>表示这个 entry 永远 valid<span class="mojikumi-line-end">，</span>不被清除/替换</li>
<li><a href="#tlb-issue-context-switches">ASID</a></li>
</ul>
<h3 id="tlb-issue-context-switches" class="heading"><a href="#tlb-issue-context-switches" class="heading-anchor" aria-label="章节： TLB Issue: Context Switches" tabindex="-1"></a><span>TLB Issue: Context Switches</span></h3>
<p>由于每个 process 的 page table 不同<span class="mojikumi-line-end">，</span>context switch 时需要处理 TLB 的更新<span class="mojikumi-line-end">。</span></p>
<p>一种方法是在 context switch 时完全清空 TLB<span class="mojikumi-line-start">（</span>将 valid bit 全部置 0<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>但这样的话每次 context switch 后都会 TLB miss<span class="mojikumi-line-end">，</span>性能较差<span class="mojikumi-line-end">。</span></p>
<p>另一种方法是在 TLB 中存储 <i>address space identifier</i> (ASID)<span class="mojikumi-line-end">，</span>它与 PID 类似<span class="mojikumi-line-end">，</span>用来表示这个 TLB entry 对应于哪个 address space<span class="mojikumi-line-end">。</span>查找 TLB 时<span class="mojikumi-line-end">，</span>需要同时比较 VPN 和 ASID<span class="mojikumi-line-end">。</span>这样既保证了不同 process 访问到不同的 page table<span class="mojikumi-line-end">，</span>又不至于在 context switch 时完全损失掉 TLB<span class="mojikumi-line-end">。</span></p>
<h3 id="issue-replacement-policy" class="heading"><a href="#issue-replacement-policy" class="heading-anchor" aria-label="章节： Issue: Replacement Policy" tabindex="-1"></a><span>Issue: Replacement Policy</span></h3>
<p>如果 TLB 满了<span class="mojikumi-line-end">，</span>添加新的 entry 时需要替换掉一个旧的<span class="mojikumi-line-end">，</span>需要根据 <a href="#beyond-physical-memory-policies">replacement policy</a> 进行选择<span class="mojikumi-line-end">。</span></p>
<h2 id="paging-smaller-tables" class="heading"><a href="#paging-smaller-tables" class="heading-anchor" aria-label="章节： Paging: Smaller Tables" tabindex="-1"></a><span>Paging: Smaller Tables</span></h2>
<p>接下来还需要优化 page table 的 space overhead<span class="mojikumi-line-end">，</span>即减小 page table 自身占用的 memory<span class="mojikumi-line-end">。</span>在优化前<span class="mojikumi-line-end">，</span>一个 32-bit address space 在 page size 为 4KB<span class="mojikumi-line-end">、</span>PTE 占用 4B 时需要占用 4MB 的空间<span class="mojikumi-line-end">。</span></p>
<h3 id="simple-solution-bigger-pages" class="heading"><a href="#simple-solution-bigger-pages" class="heading-anchor" aria-label="章节： Simple Solution: Bigger Pages" tabindex="-1"></a><span>Simple Solution: Bigger Pages</span></h3>
<p>增大 page size 可以让 PTE 数量变少<span class="mojikumi-line-end">，</span>从而减小 page table 占用的空间<span class="mojikumi-line-end">。</span>但更大的 page size 可能导致严重的 internal fragmentation<span class="mojikumi-line-end">，</span>所以不能盲目扩大<span class="mojikumi-line-end">。</span></p>
<p>有的 OS 确实支持更大的 page size<span class="mojikumi-line-end">，</span>但其目的是降低 TLB 的占用<span class="mojikumi-line-end">，</span>提升 TLB hit rate<span class="mojikumi-line-end">，</span>而非减小 page table size<span class="mojikumi-line-end">。</span></p>
<h3 id="hybrid-approach-paging-and-segments" class="heading"><a href="#hybrid-approach-paging-and-segments" class="heading-anchor" aria-label="章节： Hybrid Approach: Paging and Segments" tabindex="-1"></a><span>Hybrid Approach: Paging and Segments</span></h3>
<p>可以尝试将 paging 和 segmentation 的优点结合起来<span class="mojikumi-line-end">：</span>整体进行 segmentation<span class="mojikumi-line-end">，</span>在 segment 内部使用 paging<span class="mojikumi-line-end">，</span>每个 segment 各有一个 page table<span class="mojikumi-line-end">，</span>base 和 bounds 指向 page table<span class="mojikumi-line-end">。</span>这样的话<span class="mojikumi-line-end">，</span>address space 中不属于任何一个 segment 的部分无需占用 page table 的空间<span class="mojikumi-line-end">。</span></p>
<p>然而<span class="mojikumi-line-end">，</span>这种做法依然有很多问题<span class="mojikumi-line-end">：</span></p>
<ul>
<li>需要 segmentation<span class="mojikumi-line-end">，</span>损失了一些 flexibility<span class="mojikumi-line-end">。</span></li>
<li>一个 segment 的内部如果太 sparse<span class="mojikumi-line-end">，</span>其 page table 依然会很大<span class="mojikumi-line-end">。</span></li>
<li>虽然分配给 program 的 memory 是以 page 为单位的<span class="mojikumi-line-end">，</span>但现在 page table 变成了 variable-sized<span class="mojikumi-line-end">，</span>为 page table 分配空间又变得困难<span class="mojikumi-line-end">，</span>会产生 external fragmentation<span class="mojikumi-line-end">。</span></li>
</ul>
<h3 id="multi-level-page-tables" class="heading"><a href="#multi-level-page-tables" class="heading-anchor" aria-label="章节： Multi-level Page Tables" tabindex="-1"></a><span>Multi-level Page Tables</span></h3>
<p>很多 modern system 使用的都是 multi-level page table<span class="mojikumi-line-end">：</span>将 page table 分成多级形成树状结构<span class="mojikumi-line-end">，</span>上一级 PTE 在 valid 时指向下一级 page table<span class="mojikumi-line-end">，</span>访问上一级使用的 index 是对应的下一级的 index 的公共前缀<span class="mojikumi-line-end">。</span></p>
<p>这样做既省下了大量 invalid PTE 占用的空间<span class="mojikumi-line-end">，</span>又避免了上述 hybrid approach 的缺点<span class="mojikumi-line-end">。</span>一个 page table 的 size 可以控制在一个 page<span class="mojikumi-line-end">，</span>这也使得为 page table 自身分配 memory 更加容易<span class="mojikumi-line-end">。</span></p>
<p>但它也有一些缺点<span class="mojikumi-line-end">：</span>在 TLB miss 时<span class="mojikumi-line-end">，</span>需要访问多个 level 的 page table<span class="mojikumi-line-end">，</span>即多次 memory access<span class="mojikumi-line-end">，</span>开销更大<span class="mojikumi-line-end">；</span>实现起来更复杂<span class="mojikumi-line-end">。</span></p>
<h3 id="inverted-page-tables" class="heading"><a href="#inverted-page-tables" class="heading-anchor" aria-label="章节： Inverted Page Tables" tabindex="-1"></a><span>Inverted Page Tables</span></h3>
<p>普通的 page table 是对每个 VPN 有一个 entry 存 PFN<span class="mojikumi-line-end">，</span>而 inverted page table 则是对每个 PFN 有一个 entry 存 VPN<span class="mojikumi-line-end">，</span>并且所有 process 共用一张 inverted page table<span class="mojikumi-line-end">，</span>每个 entry 还会记录对应的 process<span class="mojikumi-line-end">。</span>为了快速查询<span class="mojikumi-line-end">，</span>需要用一些数据结构维护这张 table<span class="mojikumi-line-end">，</span>例如 hash table<span class="mojikumi-line-end">。</span></p>
<h3 id="swapping-the-page-tables-to-disk" class="heading"><a href="#swapping-the-page-tables-to-disk" class="heading-anchor" aria-label="章节： Swapping the Page Tables to Disk" tabindex="-1"></a><span>Swapping the Page Tables to Disk</span></h3>
<p>实际上<span class="mojikumi-line-end">，</span>page table 不一定放在 physical memory 中<span class="mojikumi-line-end">，</span>也可能它自身就使用 virtual memory<span class="mojikumi-line-end">，</span>这使得 page table 自身可以被 swap 到 disk 上<span class="mojikumi-line-end">，</span>避免 physical memory 放不下 page table<span class="mojikumi-line-end">。</span></p>
<h2 id="beyond-physical-memory-mechanisms" class="heading"><a href="#beyond-physical-memory-mechanisms" class="heading-anchor" aria-label="章节： Beyond Physical Memory: Mechanisms" tabindex="-1"></a><span>Beyond Physical Memory: Mechanisms</span></h2>
<p>physical memory 可能装不下整个 virtual memory<span class="mojikumi-line-start">（</span>所有 process 的 address space<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>这时可以将一部分 page 存在 disk 上<span class="mojikumi-line-end">。</span>支持更大的 virtual memory<span class="mojikumi-line-end">，</span>一方面可以让 programmer 无需考虑 memory 不够用要怎么办<span class="mojikumi-line-end">，</span>另一方面可以在 physical memory 有限的情况下支持更多 process 同时运行<span class="mojikumi-line-end">。</span></p>
<h3 id="swap-space" class="heading"><a href="#swap-space" class="heading-anchor" aria-label="章节： Swap Space" tabindex="-1"></a><span>Swap Space</span></h3>
<p>为了将 page 存储在 disk 上<span class="mojikumi-line-end">，</span>需要在 disk 上预留出一块 <i>swap space</i><span class="mojikumi-line-end">。</span>OS 可以通过 disk address 读写 swap space<span class="mojikumi-line-end">。</span></p>
<p>只不过<span class="mojikumi-line-end">，</span>swap space 并不是 swapping 在 disk 上唯一的数据来源<span class="mojikumi-line-end">，</span>例如<span class="mojikumi-line-end">，</span>program 存储在 disk 上<span class="mojikumi-line-end">，</span>所以可以从 disk 上 load<span class="mojikumi-line-end">，</span>无需再保存到 swap space<span class="mojikumi-line-end">。</span></p>
<h3 id="page-fault" class="heading"><a href="#page-fault" class="heading-anchor" aria-label="章节： Page Fault" tabindex="-1"></a><span>Page Fault</span></h3>
<p>为了支持 swapping<span class="mojikumi-line-end">，</span>需要在 PTE 中增加 <i>present bit</i><span class="mojikumi-line-end">，</span>表示这个 page 是否在 physical memory 中<span class="mojikumi-line-end">。</span>如果访问了不在 physical memory 中的 page<span class="mojikumi-line-end">，</span>则会触发 <i>page fault</i><sup><a href="#user-content-fn-page-fault" id="user-content-fnref-page-fault" data-footnote-ref aria-describedby="footnote-label">6</a></sup><span class="mojikumi-line-end">。</span></p>
<p>无论使用 software-managed TLB 还是 hardware-managed TLB<span class="mojikumi-line-end">，</span>page fault 都是由 OS 提供的 page fault handler 处理的<span class="mojikumi-line-end">。</span>这是因为 page fault 不适合由 hardware 处理<span class="mojikumi-line-end">：</span>一方面<span class="mojikumi-line-end">，</span>disk 速度慢<span class="mojikumi-line-end">，</span>访问耗时长<span class="mojikumi-line-end">；</span>另一方面<span class="mojikumi-line-end">，</span>这涉及到 swap space 的使用以及 disk I/O 的处理<span class="mojikumi-line-end">，</span>流程复杂<span class="mojikumi-line-end">。</span></p>
<p>在进行 disk I/O 的过程中<span class="mojikumi-line-end">，</span>process 会处于 blocked state<span class="mojikumi-line-end">，</span>此时 OS 可以运行其他 process<span class="mojikumi-line-end">。</span></p>
<h3 id="when-memory-is-full" class="heading"><a href="#when-memory-is-full" class="heading-anchor" aria-label="章节： When memory is full" tabindex="-1"></a><span>When memory is full</span></h3>
<p>在 <i>page in</i> 的时候<span class="mojikumi-line-end">，</span>如果 physical memory 满了<span class="mojikumi-line-end">，</span>则需要先 <i>page out</i> 一些 page<span class="mojikumi-line-end">，</span>OS 通过 <a href="#beyond-physical-memory-policies"><i>page-replacement policy</i></a> 选择这些 page<span class="mojikumi-line-end">。</span></p>
<p>只不过<span class="mojikumi-line-end">，</span>一般并不会等到 physical memory 完全耗尽才进行 page out<span class="mojikumi-line-end">，</span>而是会在剩余的 physical memory 不多时就在 background 运行 <i>swap daemon</i><span class="mojikumi-line-end">，</span>evict 掉一些 page<span class="mojikumi-line-end">，</span>来保持 physical memory 有一定量的空余<span class="mojikumi-line-end">。</span>这样一方面可以批量处理<span class="mojikumi-line-end">，</span>效率更高<span class="mojikumi-line-start">（</span>尤其是 disk I/O<span class="mojikumi">）</span><span class="mojikumi-line-end">，</span>另一方面<span class="mojikumi-line-end">，</span>在 background 运行可以更好地利用 idle time<span class="mojikumi-line-end">。</span></p>
<h2 id="beyond-physical-memory-policies" class="heading"><a href="#beyond-physical-memory-policies" class="heading-anchor" aria-label="章节： Beyond Physical Memory: Policies" tabindex="-1"></a><span>Beyond Physical Memory: Policies</span></h2>
<p>由于 disk 访问速度非常慢<span class="mojikumi-line-end">，</span>page hit rate 略微提高一点<span class="mojikumi-line-end">，</span>average memory access time 就可以下降很多<span class="mojikumi-line-end">，</span>所以使用一个好的 replacement policy 非常重要<span class="mojikumi-line-end">。</span></p>
<p><span class="mojikumi-line-start">（</span>当然<span class="mojikumi-line-end">，</span>为了获得更好的性能<span class="mojikumi-line-end">，</span>也可以选择增大 physical memory<span class="mojikumi">。</span><span class="mojikumi-line-end">）</span></p>
<h3 id="replacement-policies" class="heading"><a href="#replacement-policies" class="heading-anchor" aria-label="章节： Replacement Policies" tabindex="-1"></a><span>Replacement Policies</span></h3>
<p>为了衡量 replacement policy 的优劣<span class="mojikumi-line-end">，</span>由于 hit rate 受到具体 sample 的影响<span class="mojikumi-line-end">，</span>光看 hit rate 会缺少一些 context<span class="mojikumi-line-end">，</span>可以和 optimal policy (OPT) 进行比较<span class="mojikumi-line-end">。</span>假设可以预知未来<span class="mojikumi-line-end">，</span>可以证明<span class="mojikumi-line-end">，</span>最优的 policy 是 <i>furthest in the future</i><span class="mojikumi-line-end">，</span>即每次 evict 掉最远会被再次访问的 page<span class="mojikumi-line-end">。</span>当然<span class="mojikumi-line-end">，</span>实际上是无法预知未来的<span class="mojikumi-line-end">，</span>所以需要使用其他尽量优的 policy<span class="mojikumi-line-end">。</span></p>
<p>FIFO 和 random 是两种简单的 policy<span class="mojikumi-line-end">，</span>他们实现简单<span class="mojikumi-line-end">，</span>但比较笨<span class="mojikumi-line-end">，</span>容易 evict 掉频繁访问的 important page<span class="mojikumi-line-end">。</span></p>
<p>和 <a href="#scheduling-introduction">scheduling policy</a> 一样<span class="mojikumi-line-end">，</span>可以基于历史预测未来<span class="mojikumi-line-end">，</span>来逼近最优<span class="mojikumi-line-end">。</span>replacement policy 主要关注 page 的 <i>frequency</i> 和 <i>recency</i><span class="mojikumi-line-end">，</span>其原理是 program 的 locality<span class="mojikumi-line-end">。</span>有 <i>least-frequently-used</i> (LFU)<span class="mojikumi-line-end">、</span><i>least-recently-used</i> (LRU)<span class="mojikumi-line-end">，</span>以及相反的 MFU<span class="mojikumi-line-end">、</span>MRU 等 policy<span class="mojikumi-line-end">，</span>其中 LRU 是最常用<span class="mojikumi-line-end">，</span>效果较好的<span class="mojikumi-line-end">，</span>实现相对简单的<span class="mojikumi-line-end">。</span></p>
<h3 id="workload-examples" class="heading"><a href="#workload-examples" class="heading-anchor" aria-label="章节： Workload Examples" tabindex="-1"></a><span>Workload Examples</span></h3>
<p>完全随机访问<span class="mojikumi-line-end">，</span>没有 locality<span class="mojikumi-line-end">：</span>FIFO<span class="mojikumi-line-end">、</span>random<span class="mojikumi-line-end">、</span>LRU 表现相同<span class="mojikumi-line-end">，</span>hit rate 和 cache size 成正比<span class="mojikumi-line-end">。</span></p>
<p><picture><img type="image/webp" srcset="/assets/ostep-fig-22.6.6aceca2f.webp" loading="lazy" src="/assets/ostep-fig-22.6.6aceca2f.webp" width="426" height="413" alt="Figure 22.6: The No-Locality Workload"></picture></p>
<p>80% 的访问集中在 20% 的 <span class="mojikumi">“</span>hot<span class="mojikumi">”</span> page<span class="mojikumi-line-end">：</span>LRU 的性能介于 FIFO/random 和 OPT 之间<span class="mojikumi-line-end">。</span></p>
<p><picture><img type="image/webp" srcset="/assets/ostep-fig-22.7.7b4121db.webp" loading="lazy" src="/assets/ostep-fig-22.7.7b4121db.webp" width="425" height="414" alt="Figure 22.7: The 80-20 Workload"></picture></p>
<p>循环访问若干个 page<span class="mojikumi-line-end">：</span>在 cache size 足够大时各种 policy 都是 100% hit<span class="mojikumi-line-end">，</span>在 cache size 较小时<span class="mojikumi-line-end">，</span>LRU 和 FIFO 会退化至 100% miss<span class="mojikumi-line-end">，</span>random 仍有合理的性能<span class="mojikumi-line-end">。</span></p>
<p><picture><img type="image/webp" srcset="/assets/ostep-fig-22.8.666be521.webp" loading="lazy" src="/assets/ostep-fig-22.8.666be521.webp" width="425" height="413" alt="Figure 22.8: The Looping Workload"></picture></p>
<p>也就是说<span class="mojikumi-line-end">，</span>LRU 虽然一般性能较好<span class="mojikumi-line-end">，</span>但在 corner case 下性能会很差<span class="mojikumi-line-end">。</span>现在的 OS 一般会采取一些额外的措施来做到 <i>scan resistant</i><span class="mojikumi-line-end">，</span>避免 worst-case behavior<span class="mojikumi-line-end">。</span></p>
<h3 id="implementing-lru" class="heading"><a href="#implementing-lru" class="heading-anchor" aria-label="章节： Implementing LRU" tabindex="-1"></a><span>Implementing LRU</span></h3>
<p>LRU 的实现需要记录每一次 memory access<span class="mojikumi-line-end">，</span>精确实现比较 expensive<span class="mojikumi-line-end">，</span>所以一般只是取近似<span class="mojikumi-line-end">。</span></p>
<p>在 page table 中会为每个 page 存一个 <i>reference bit</i><span class="mojikumi-line-end">，</span>访问一个 page 时 hardware 会将 reference bit 置为 1<span class="mojikumi-line-end">。</span></p>
<p>OS 可以用各种方式使用 reference bit 来逼近 LRU<span class="mojikumi-line-end">，</span>例如 <i>clock algorithm</i><span class="mojikumi-line-end">：</span>循环扫描所有 page<span class="mojikumi-line-end">，</span>如果 reference bit 为 1 则置为 0 然后继续扫描<span class="mojikumi-line-end">，</span>直到 reference bit 为 0<span class="mojikumi-line-end">，</span>选择这个 page<span class="mojikumi-line-end">。</span>也不一定要循环扫描<span class="mojikumi-line-end">，</span>可以随机选择<span class="mojikumi-line-end">。</span></p>
<p><picture><img type="image/webp" srcset="/assets/ostep-fig-22.9.1824a7d2.webp" loading="lazy" src="/assets/ostep-fig-22.9.1824a7d2.webp" width="426" height="410" alt="Figure 22.9: The 80-20 Workload With Clock"></picture></p>
<h3 id="considering-dirty-pages" class="heading"><a href="#considering-dirty-pages" class="heading-anchor" aria-label="章节： Considering Dirty Pages" tabindex="-1"></a><span>Considering Dirty Pages</span></h3>
<p>page replacement 还需要考虑一个 page 是否 <i>dirty</i><span class="mojikumi-line-end">，</span>即是否被修改过<span class="mojikumi-line-end">。</span>dirty page 被 evict 时需要将数据写回到 disk 上<span class="mojikumi-line-end">，</span>clean page 则不需要<span class="mojikumi-line-end">。</span>所以 evict dirty page 更加 expensive<span class="mojikumi-line-end">，</span>replacement policy 一般会考虑优先选择 clean page<span class="mojikumi-line-end">。</span>例如在 clock algorithm 中可以先扫描一轮 clean page<span class="mojikumi-line-end">，</span>没找到再扫描 dirty page<span class="mojikumi-line-end">。</span></p>
<h3 id="other-vm-policies" class="heading"><a href="#other-vm-policies" class="heading-anchor" aria-label="章节： Other VM Policies" tabindex="-1"></a><span>Other VM Policies</span></h3>
<p>除了 replacement policy<span class="mojikumi-line-end">，</span>OS 还需要考虑何时将一个 page 放进 physical memory<span class="mojikumi-line-end">。</span>普通的做法是 <i>demand paging</i><span class="mojikumi-line-end">，</span>即等到真的使用的时候才 page in<span class="mojikumi-line-end">。</span>有时也可以进行 <i>prefetch</i><span class="mojikumi-line-end">，</span>例如在使用一个 page 的同时 load 相邻的下一个 page<span class="mojikumi-line-end">，</span>或者在 program 提供 hint 时进行 prefetch<span class="mojikumi-line-end">。</span></p>
<p>另一个 policy 是何时将 page 写回到 disk 上<span class="mojikumi-line-end">，</span>可以进行 <i>clustering</i> (<i>grouping</i>)<span class="mojikumi-line-end">，</span>进行少次多量的 disk write<span class="mojikumi-line-end">，</span>性能更好<span class="mojikumi-line-end">。</span></p>
<h3 id="thrashing" class="heading"><a href="#thrashing" class="heading-anchor" aria-label="章节： Thrashing" tabindex="-1"></a><span>Thrashing</span></h3>
<p>如果 running processes 的 <i>working set</i><span class="mojikumi-line-start">（</span>正在使用的 page<span class="mojikumi-line-end">）</span>太大<span class="mojikumi-line-end">，</span>physical memory 装不下<span class="mojikumi-line-end">，</span>就会出现 <i>thrashing</i><span class="mojikumi-line-end">，</span>会一直进行 paging<span class="mojikumi-line-end">，</span>极大影响系统性能<span class="mojikumi-line-end">。</span></p>
<p>早期的系统 physical memory 较小<span class="mojikumi-line-end">，</span>出现这种情况比较正常<span class="mojikumi-line-end">，</span>可以使用 <i>admission control</i><span class="mojikumi-line-end">，</span>暂停一部分 process 的运行<span class="mojikumi-line-end">，</span>以减小 working set<span class="mojikumi-line-end">。</span></p>
<p>现在的系统则一般会使用 <i>out-of-memory killer</i><span class="mojikumi-line-end">，</span>在 memory 占用过高时 kill 掉一些 process<span class="mojikumi-line-end">。</span></p>
<h2 id="complete-virtual-memory-systems" class="heading"><a href="#complete-virtual-memory-systems" class="heading-anchor" aria-label="章节： Complete Virtual Memory Systems" tabindex="-1"></a><span>Complete Virtual Memory Systems</span></h2>
<h3 id="vaxvms-virtual-memory" class="heading"><a href="#vaxvms-virtual-memory" class="heading-anchor" aria-label="章节： VAX/VMS Virtual Memory" tabindex="-1"></a><span>VAX/VMS Virtual Memory</span></h3>
<p>VAX/VMS 是 1970/80 年代的系统<span class="mojikumi-line-end">，</span>有很多 idea 延续至今<span class="mojikumi-line-end">。</span></p>
<p>address space 被分成 <i>process space</i> 和 <i>system space</i> 两部分<span class="mojikumi-line-end">。</span>process space 又被分成 <i>P0</i> 用来放 code 和 heap<span class="mojikumi-line-end">，</span>以及 <i>P1</i> 用来放 stack<span class="mojikumi-line-end">，</span>而 system space <i>(S)</i> 用来放 OS code 和 data<span class="mojikumi-line-end">，</span>在 protection bits 中设置了更高的 privilege level<span class="mojikumi-line-end">。</span></p>
<p>page size 只有 512B<span class="mojikumi-line-end">，</span>因此优化 page table 占用的空间非常重要<span class="mojikumi-line-end">。</span>它使用的是 <a href="#hybrid-approach-paging-and-segments">hybrid of paging and segmentation</a><span class="mojikumi-line-end">，</span>并且 page table 放在 kernel virtual memory 中<span class="mojikumi-line-end">，</span>可以 swap 到 disk 上<span class="mojikumi-line-end">。</span></p>
<p>code segment 的 address 并非从 0 开始<span class="mojikumi-line-end">，</span>从而可以检测到 null-pointer access<span class="mojikumi-line-end">。</span></p>
<p>kernel address space 是 user address space 的一部分<span class="mojikumi-line-end">，</span>在 context switch 时只更改 P0 和 P1 的 base and bounds<span class="mojikumi-line-end">，</span>不更改 S<span class="mojikumi-line-end">。</span>为 kernel 使用 virtual address 便于 swap page table to disk<span class="mojikumi-line-end">，</span>也便于在 kernel 和 user program 之间 copy data<span class="mojikumi-line-end">。</span></p>
<p>VAX 的 hardware 不维护 reference bit<span class="mojikumi-line-end">，</span>VMS 实现的也不是 LRU<span class="mojikumi-line-end">，</span>而是 <i>segmented FIFO</i><span class="mojikumi-line-end">：</span></p>
<ul>
<li>每个 process 有自己的 FIFO list<span class="mojikumi-line-end">，</span>另有 global 的 clean page list 和 dirty page list<span class="mojikumi-line-end">。</span></li>
<li>对每个 process 限制了 <i>resident set size</i> (RSS)<span class="mojikumi-line-end">，</span>以防止单个 process 占用过多 memory<span class="mojikumi-line-end">。</span></li>
<li>一个 process 使用的 page 数量超过 RSS 之后<span class="mojikumi-line-end">，</span>会将 process FIFO list 里的 page 移到 global list<span class="mojikumi-line-start">（</span>保留在 physical memory 中不 evict<span class="mojikumi">）</span><span class="mojikumi-line-end">。</span></li>
<li>需要进行 page replacement 时从 global clean page list 取<span class="mojikumi-line-end">。</span></li>
<li>如果 access 了一个在 global list 的 page<span class="mojikumi-line-end">，</span>则将其移回 process FIFO list<span class="mojikumi-line-end">。</span></li>
<li>定期将 dirty page list 批量写回到 disk<span class="mojikumi-line-end">，</span>然后移动到 clean page list<span class="mojikumi-line-end">。</span></li>
</ul>
<p>有两个 lazy optimization<span class="mojikumi-line-end">：</span></p>
<dl>
<dt>demand zeroing</dt>
<dd>request 一个 page 时<span class="mojikumi-line-end">，</span>为了 security 需要将其内容清空<span class="mojikumi-line-end">，</span>但不需要立即清空<span class="mojikumi-line-end">，</span>而是可以等到真正被使用了再清空<span class="mojikumi-line-end">，</span>如果最后没被使用就不用清空了<span class="mojikumi-line-end">。</span>
</dd>
<dt>copy-on-write</dt>
<dd>复制 page 时先将两边都设为 read-only 并指向相同的 physical memory<span class="mojikumi-line-end">，</span>写入时会触发 trap<span class="mojikumi-line-end">，</span>然后再真的进行 copy 并设为 writable<span class="mojikumi-line-end">。</span>这对 <code>fork()</code> 尤其有用<span class="mojikumi-line-end">。</span>
</dd>
</dl>
<h3 id="the-linux-virtual-memory-system" class="heading"><a href="#the-linux-virtual-memory-system" class="heading-anchor" aria-label="章节： The Linux Virtual Memory System" tabindex="-1"></a><span>The Linux Virtual Memory System</span></h3>
<p>Linux address space 分为 user portion 和 kernel portion<span class="mojikumi-line-end">。</span></p>
<p>kernel virtual address 分为两种<span class="mojikumi-line-end">：</span></p>
<ul>
<li><i>kernel logical address</i><span class="mojikumi-line-end">，</span>使用 <code>kmalloc</code> 获取<span class="mojikumi-line-end">，</span>不能 swap to disk<span class="mojikumi-line-end">，</span>和 physical address 是相差固定 offset 的简单对应关系<span class="mojikumi-line-end">，</span>所以对应的 physical address 是连续的<span class="mojikumi-line-end">，</span>适用于 direct memory access 等场景<span class="mojikumi-line-end">。</span></li>
<li><i>kernel virtual address</i><span class="mojikumi-line-end">，</span>使用 <code>vmalloc</code> 获取<span class="mojikumi-line-end">，</span>更容易分配大块的 memory<span class="mojikumi-line-end">，</span>对应的 physical address 不一定是连续的<span class="mojikumi-line-end">。</span></li>
</ul>
<p>Linux 支持 <i>huge page</i><span class="mojikumi-line-end">。</span>以前需要 program 主动请求使用 huge page<span class="mojikumi-line-end">，</span>后来又有了 <i>transparent huge page</i><span class="mojikumi-line-end">，</span>可以自动使用更大的 page size<span class="mojikumi-line-end">，</span>以在 working set 很大时减少 TLB miss<span class="mojikumi-line-end">。</span>只不过更大的 page size 也可能造成更严重的 internal fragmentation<span class="mojikumi-line-end">。</span></p>
<p>Linux 中有两种 memory mapping<span class="mojikumi-line-end">：</span>memory-mapped file 和 anonymous memory<span class="mojikumi-line-end">。</span>前者可以 map file to memory<span class="mojikumi-line-end">，</span>常用于 load program 以及 shared library<span class="mojikumi-line-end">，</span>从而一个 page 等到真正使用才会从 disk 读取<span class="mojikumi-line-end">，</span>称作 <i>depand paging</i><span class="mojikumi-line-end">；</span>后者用于 heap 和 stack<span class="mojikumi-line-end">。</span></p>
<p>Linux 使用 <i>2Q</i> replacement policy<span class="mojikumi-line-end">，</span>以解决 LRU 的 worst-case behavior<span class="mojikumi-line-end">：</span></p>
<ul>
<li>有两个 queue<span class="mojikumi-line-end">，</span><i>inactive list</i> 和 <i>active list</i><span class="mojikumi-line-end">，</span>分别近似 LRU</li>
<li>首次访问 page 会进入 inactive list<span class="mojikumi-line-end">，</span>再次访问则进入 active list</li>
<li>定期将一些 page 从 active list 移入 inactive list</li>
<li>evict 时优先选择 inactive list</li>
</ul>
<p>这样的话<span class="mojikumi-line-end">，</span>inactive page 就不会将 active page 挤出 physical memory<span class="mojikumi-line-end">。</span></p>
<p>为了缓解 buffer overflow attack<span class="mojikumi-line-end">，</span>permission bits 中需要添加 <i>NX bit</i> (no-execute)<span class="mojikumi-line-end">，</span>并且使用 <i>address space layout randomization</i> (ASLR)<span class="mojikumi-line-end">。</span></p>
<p>为了缓解 <a href="https://spectreattack.com">Meltdown/Spectre attack</a><span class="mojikumi-line-end">，</span>可以创建单独的 kernel address space<span class="mojikumi-line-end">，</span>称作 <i>kernel page-table isolation</i> (KPTI)<span class="mojikumi-line-end">，</span>在切换到 kernel mode 时需要切换 page table<span class="mojikumi-line-end">，</span>这对性能有一定的影响<span class="mojikumi-line-end">。</span></p>
<section data-footnotes class="footnotes"><h2 class="sr-only" id="footnote-label">Footnotes</h2>
<ol>
<li id="user-content-fn-cake">
<p>作者推荐阅读<span class="mojikumi-line-end">：</span><a href="https://en.wikipedia.org/wiki/You_can%27t_have_your_cake_and_eat_it">You can't have your cake and eat it - Wikipedia</a><br>
<span class="mojikumi-line-start">“</span>The best part of this page is reading all the similar idioms from other languages.<span class="mojikumi-line-end">”</span> <a href="#user-content-fnref-cake" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-contiguous">
<p>注意是 <span class="mojikumi">“</span>contiguous<span class="mojikumi">”</span> 而不是 <span class="mojikumi">“</span>continuous<span class="mojikumi">”</span><span class="mojikumi-line-end">，</span><s>discrete topology 下随便 map 都 continuous<span class="mojikumi-line-start">（</span></s> <a href="#user-content-fnref-contiguous" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-bounds">
<p><strong>bound</strong> noun (formal) 蹦跳<span class="mojikumi-line-end">；</span>跳跃<br>
<strong>bounds</strong> noun [pl.] 限制范围<span class="mojikumi-line-end">；</span>极限 <a href="#user-content-fnref-bounds" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-wreak">
<p><span class="mojikumi-line-start">“</span>Is there anything other than <span class="mojikumi-narrow-right">‘</span>havoc<span class="mojikumi-narrow-left">’</span> that can be <span class="mojikumi-narrow-right">‘</span>wreaked<span class="mojikumi">’</span>?<span class="mojikumi-line-end">”</span><br>
我想作者可能需要一本牛津词典或者 <a href="http://www.just-the-word.com/">http<wbr>://<wbr>www<wbr>.<wbr>just<wbr>-<wbr>the<wbr>-<wbr>word<wbr>.<wbr>com<wbr>/</a> <span class="mojikumi">（</span> <a href="#user-content-fnref-wreak" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-tlb">
<p><span class="mojikumi-line-start">“</span>lookaside buffer<span class="mojikumi">”</span> 是 cache 的历史名称<span class="mojikumi-line-end">，</span>后来 <span class="mojikumi">“</span>lookaside buffer<span class="mojikumi">”</span> 被 <span class="mojikumi">“</span>cache<span class="mojikumi">”</span> 取代<span class="mojikumi-line-end">，</span>但 <span class="mojikumi">“</span>TLB<span class="mojikumi">”</span> 保留了下来<span class="mojikumi-line-end">。</span>现在看来一个更合理的名称或许应当是 <span class="mojikumi">“</span>address-translation cache<span class="mojikumi">”</span><span class="mojikumi-line-end">。</span> <a href="#user-content-fnref-tlb" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
<li id="user-content-fn-page-fault">
<p>page fault 虽然叫做 <span class="mojikumi">“</span>fault<span class="mojikumi">”</span><span class="mojikumi-line-end">，</span>但它其实是 legal access<span class="mojikumi-line-end">，</span>称它为 <span class="mojikumi">“</span>page miss<span class="mojikumi">”</span> 或许会更好<span class="mojikumi-line-end">。</span>只不过<span class="mojikumi-line-end">，</span>hardware 需要将这作为一种异常情况交给 OS 处理<span class="mojikumi-line-end">，</span>和其他 illegal action 类似<span class="mojikumi-line-end">，</span>所以称它是 <span class="mojikumi">“</span>fault<span class="mojikumi">”</span><span class="mojikumi-line-end">。</span>另外<span class="mojikumi-line-end">，</span>有时人们也会将 illegal memory access 一并统称为 <span class="mojikumi">“</span>page fault<span class="mojikumi">”</span><span class="mojikumi-line-end">，</span>可能会将 <span class="mojikumi">“</span>page fault<span class="mojikumi">”</span> 分成几类<span class="mojikumi-line-end">，</span>其中一类是 page miss<span class="mojikumi-line-end">，</span>需要根据上下文进行判断<span class="mojikumi-line-end">。</span> <a href="#user-content-fnref-page-fault" data-footnote-backref class="data-footnote-backref" aria-label="Back to content">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <category domain="https://ouuan.moe/tag/ostep">ostep</category>
            <category domain="https://ouuan.moe/tag/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0">学习笔记</category>
        </item>
    </channel>
</rss>