<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>ARui&#39;s Blog</title>
  
  
  <link href="https://blog.arui.dev/atom.xml" rel="self"/>
  
  <link href="https://blog.arui.dev/"/>
  <updated>2024-03-05T21:37:03.021Z</updated>
  <id>https://blog.arui.dev/</id>
  
  <author>
    <name>ARui</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>

  <follow_challenge>
    <feedId>73198174631757824</feedId>
    <userId>55149692133865472</userId>
  </follow_challenge>
  
  <entry>
    <title>陽明交大資工所碩一上（2023 Fall）修課心得</title>
    <link href="https://blog.arui.dev/2023FallCourses/"/>
    <id>https://blog.arui.dev/2023FallCourses/</id>
    <published>2024-03-05T18:55:00.000Z</published>
    <updated>2024-03-05T21:37:03.021Z</updated>
    
    <content type="html"><![CDATA[<h1 id="作業系統">作業系統</h1><ul><li>英文課名：Operating System</li><li>永久課號：CSIC30015</li><li>教師：吳俊峯</li></ul><h2 id="課程內容">課程內容</h2><p>因為沒上過交大這邊教的大學部OS，所以不知道跟大學的差別有多少。但是體感上跟清大差不少。清大周志遠教授的OS 感覺比較想是每個 component都碰一下，但是這堂比較偏向每個都會教到比較深層的。但可能時間的關係，所以也沒有辦法教很多很深。老師好像是作記憶體的（他下學期還有開一門〈記憶體與儲存系統〉），所以那段講的特別細節和清楚。</p><span id="more"></span><h2 id="上課方式">上課方式</h2><p>英文授課。線上實體並行，會有影片存檔。課間的學生提問都會被錄下來。基本上我除了第一堂和期中期末以外都沒去過了XDD</p><h2 id="考試作業">考試作業</h2><ul><li>20% Midterm Exam<ul><li>有人在 nctuplus 上面丟考古了，Dcard也有一個篇在討論這個。基本上跟去年考古一樣，多了一個 section的是非題。滿分依舊破百。</li></ul></li><li>30% Final Exam<ul><li>沒檢討，考卷沒發回來。會考到期中範圍，記得複習。</li></ul></li><li>20% Paper Presentation<ul><li>這年因為人數的關係兩個人一組。一組約 12~15分鐘報一篇。要從老師指定的 conferences 中選（USENIX OSDI, USENIX ATC,USENIX FAST, SOSP, ASPLOS, HPCA, ACM SC, ISCA, MICRO, EuroSys）。或是Rank A 且十頁以上的。</li><li>第二週報加兩分，第三周報加一分。用英文報加兩分。</li></ul></li><li>30% Homework<ul><li>作業一<ul><li>要改 Linux 的 uname，需要一台虛擬機。然後實作一個簡單的 systemcalls。</li></ul></li><li>作業二<ul><li>用 pthread 去作不同 policy 的 scheduling。</li></ul></li><li>作業三<ul><li>寫一個 kernel module 去印出系統資料。</li></ul></li></ul></li><li>10% Class Participation (1 question 2pts)</li></ul><h2 id="其他">其他</h2><p>不點名。線上也可以發問。</p><h2 id="最後想說的話">最後想說的話</h2><p>老師的英文很好，用近乎兩倍速也可以聽懂。解釋能力也很好，闡述都很清楚。學生問問題如果遇到他不會他也會在下次補充。可能因為有加分的關係，所以很多人在問問題。最後還有小調三分，佛！</p><p>班平均 86.85，還有不少人破百 @@</p><h1 id="校務系統開發與管理一">校務系統開發與管理（一）</h1><ul><li>英文課名：Institutional System Development and Management</li><li>永久課號：CSIC30060</li><li>教師：鄭昌杰（雖然上面寫很多人，但是基本上是鄭老師在帶。）</li></ul><h2 id="課程內容-1">課程內容</h2><p>學生上台報告和報進度。有時候會安排演講，可以跟 Sophi（我們的PM）許願。</p><h2 id="上課方式-1">上課方式</h2><p>每週會排一到兩個人上台報告。之後就是報大家這周各自的進度，老師會給你一些參考意見，但真的只是參考，他也不會強迫你作什麼。如果有遇到「人際」問題也可以在這時候提出來，人很好的Sophi 會幫你解決。基本上老師也想趕快閃人（大家都想），所以都會在 2:30分左右結束課程。</p><h2 id="考試作業-1">考試作業</h2><p>無。評分由老師評估你這學期的開發進度。基本上不要亂搞應該都會 A+</p><h2 id="其他-1">其他</h2><p>可以請假，但是不要太誇張。</p><h2 id="最後想說的話-1">最後想說的話</h2><p>戊組人們少數聚在一起的時間（？）。老師和 Sophi人都很好，有問題都可以提出來。</p><h1 id="論文研討">論文研討</h1><ul><li>英文課名：Seminars</li><li>永久課號：CSIC30115</li><li>教師：每週都有不同的講者</li></ul><h2 id="課程內容-2">課程內容</h2><p>聽演講。</p><h2 id="上課方式-2">上課方式</h2><p>每週會要請講者去演講。通常是一個小時會結束。有時候會出現跟 CS毫無關係的演講主題，像是兩性關係（超ㄏ）。多數都是企業來宣傳。</p><h2 id="考試作業-2">考試作業</h2><p>手寫 100字心得。沒寫算沒到。助教會每週更新目前大家的出席次數。聽說會真的數字數，有人在Dcard 抱怨他被抓到。</p><h2 id="其他-2">其他</h2><p>可以三次不出席。</p><h2 id="最後想說的話-2">最後想說的話</h2><p>真心希望他們可以邀請更有料的講者 ==。有記得好的應該是一次是微軟的和另一個國外大學來講。</p><h1 id="無線多媒體網路">無線多媒體網路</h1><ul><li>英文課名：Wireless Multimedia Networks</li><li>永久課號：CSIC30073</li><li>教師：趙禧綠</li></ul><h2 id="課程內容-3">課程內容</h2><ul><li>Quality of Service (QoS)</li><li>Inserve</li><li>DiffServ</li><li>MPLS</li><li>Internet Traffic Engineering</li><li>IGMP &amp; Multicasting</li><li>MIMO Beamforming</li><li>Dynamic Reuse of Unlicensed Spectrum</li><li>TSN</li></ul><h2 id="上課方式-3">上課方式</h2><p>投影片加上板書作畫。一開始沒有錄影，期中後經學生要求有錄影上傳。上課老師會想要學生的反應，但是我們這屆沒什麼反應，所以坐第一排的同學就可以一直跟老師對話XD。老師時不時會分享他實驗室的東西和他之前的經驗，可以感受到他對於這個領域的熱情。</p><h2 id="考試作業-3">考試作業</h2><ul><li>Midterm: 30%<ul><li>考題有問答和選擇。可以跟老師要去年考古，但是不會給解答。可以跟老師argue 範圍 XDD</li></ul></li><li>Final: 35%<ul><li>類似期中考。但是老師忘記給考古了 QQ</li></ul></li><li>Project: 35%<ul><li>可以一到二人，但是兩個人的要做的比一個人的難。題目自訂，老師是說拿課堂內教過的，但好像很多人拿其他課或實驗室在做的東西來延伸？期末考前有一次Proposal報告，老師會給意見和評價難度。期末後的報告是線上報告，這年是另外約時間。</li></ul></li></ul><h2 id="其他-3">其他</h2><p>不點名，但是強烈建議到課。自己啃講義或是原文書很痛苦……</p><h2 id="最後想說的話-3">最後想說的話</h2><p>老師會把 5G 念成「五雞」，把 Wi-Fi 念成「歪ㄈㄞ」。</p><p>老師的解釋都很清楚，但是小生駑鈍，很多之前學過的東西都忘記了。下課可以去找老師一直問到懂為止。有時候太多人問一樣的問題老師會叫已經問過的同學講給剛來的同學。可能因為小班的關係，老師都很free，想要什麼都可以問問看。</p><p>最後成績看不到細項，但是拿 A+ 就沒有去跟老師問成績了 XD</p><h1 id="網路安全">網路安全</h1><ul><li>英文課名：Network Security</li><li>永久課號：CSIC30093</li><li>教師：謝續平</li></ul><h2 id="課程內容-4">課程內容</h2><p>基本上就是照著《William Stallings, Network Security Essentials –Applications and Standards, Pearson》的各個章節。</p><h2 id="上課方式-4">上課方式</h2><p>投影片加上口述補充。</p><h2 id="考試作業-4">考試作業</h2><p>老師說會在根據當年的成績調整分配。</p><ul><li>Midterm Exam: 30% ± 10%<ul><li>考前六章，交大資工考古題系統上面有考古。有一定的題數會和前幾年的重複。建議可以多刷幾年。</li></ul></li><li>Final Exam: 30% ± 10%<ul><li>大致跟期中考一樣。</li></ul></li><li>Project + Homeworks + quizzes: 40% +- 20%<ul><li>Project 是從助教給的 CVE中挑一個出來重現，建議早點開始挑個簡單的來寫。報告要分三次交，每次會有不同的進度。基本上分數很好拿，全班平均超高。</li></ul></li></ul><h2 id="其他-4">其他</h2><p>不點名，沒線上，沒錄影。會有 pop quiz。這學期遇到兩次。</p><h2 id="最後想說的話-4">最後想說的話</h2><p>甜爛。建議去上課，拿原文書啃很花時間，但是可以學到比較多東西。 <imgsrc="/assets/2023FallCourses/score.png" alt="Untitled" /></p><h1 id="軟體定義網路及網路功能虛擬化">軟體定義網路及網路功能虛擬化</h1><ul><li>英文課名：Software Defined Networks and Network FunctionVirtualization</li><li>永久課號：CSIC30127</li><li>教師：曾建超（超哥）</li></ul><h2 id="課程內容-5">課程內容</h2><p>沒…沒在上課 Orz</p><h2 id="上課方式-5">上課方式</h2><p>投影片加上口述補充。</p><h2 id="考試作業-5">考試作業</h2><ul><li>大概每兩週一個 Lab，deadline 的下一周要去實體 Demo。週而復始直到寫完Final Project :)</li><li>Labs<ol type="1"><li>Environment Setup and Basic Operation (5%)</li><li>OpenFlow Protocol Observation and Flow Rule Installation (10%)</li><li>SDN-enabled Learning Bridge (15%)</li><li>Unicast DHCP Application (15%)</li><li>Proxy ARP (15%)</li><li>Network Function Virtualization (15%)</li></ol></li><li>Final Project: (25%)<ul><li>Virtual Routers</li><li>基本上就是把前面的東西串起來</li></ul></li></ul><h2 id="其他-5">其他</h2><p>不點名，有線上，有錄影。因為沒考試，所以只要可以把功課寫出來，不上課也不會真的出大事（？</p><h2 id="最後想說的話-5">最後想說的話</h2><p>希望超哥不會看到我沒上課 QQ</p>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;作業系統&quot;&gt;作業系統&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;英文課名：Operating System&lt;/li&gt;
&lt;li&gt;永久課號：CSIC30015&lt;/li&gt;
&lt;li&gt;教師：吳俊峯&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;課程內容&quot;&gt;課程內容&lt;/h2&gt;
&lt;p&gt;因為沒上過交大這邊教的大學部
OS，所以不知道跟大學的差別有多少。但是體感上跟清大差不少。清大周志遠教授的
OS 感覺比較想是每個 component
都碰一下，但是這堂比較偏向每個都會教到比較深層的。但可能時間的關係，所以也沒有辦法教很多很深。老師好像是作記憶體的（他下學期還有開一門〈記憶體與儲存系統〉），所以那段講的特別細節和清楚。&lt;/p&gt;</summary>
    
    
    
    <category term="NYCU" scheme="https://blog.arui.dev/categories/NYCU/"/>
    
    
    <category term="NYCU" scheme="https://blog.arui.dev/tags/NYCU/"/>
    
    <category term="Course" scheme="https://blog.arui.dev/tags/Course/"/>
    
  </entry>
  
  <entry>
    <title>從中華郵政匯款到 Firstrade 的美元帳戶</title>
    <link href="https://blog.arui.dev/PostToFirstrade/"/>
    <id>https://blog.arui.dev/PostToFirstrade/</id>
    <published>2024-02-24T15:27:00.000Z</published>
    <updated>2024-02-24T17:05:22.327Z</updated>
    
    <content type="html"><![CDATA[<h1 id="tldr">TL;DR</h1><p>從郵局匯款到Fristrade，綁定約定到入帳最快可能可以<strong>四天完成</strong>。兩天是綁定的時間，兩天是匯款的時間。郵局這邊的手續費因為活動期間，用行動郵局App 轉帳只要 168。之後最便宜應該也要 <ahref="https://www.post.gov.tw/post/internet/B_saving/index.jsp?ID=3020204">300+ 100</a>。<strong>中轉行收 15 USD</strong>。</p><span id="more"></span><h1 id="時間線">時間線</h1><ul><li><code>2024/02/15 17:00</code> 申請綁定約定帳戶</li><li><code>2024/02/17 12:01</code> 通知綁定完成</li><li><code>2024/02/19 14:19</code> 匯款至 Firstrade</li><li><code>2024/02/21 09:26</code> 看到 Fristrade 收到款項</li><li><code>2024/02/21 晚上</code> 申請匯款補助</li><li><code>2024/02/21 下午</code> 收到匯款補助</li></ul><h1 id="費用">費用</h1><table><thead><tr class="header"><th>項目</th><th>金額</th></tr></thead><tbody><tr class="odd"><td>申請綁定約定帳戶</td><td>NT$0</td></tr><tr class="even"><td>郵局匯款（活動期間）</td><td>NT$158</td></tr><tr class="odd"><td>中轉行</td><td>US$15</td></tr><tr class="even"><td>Firstrade 補助</td><td>-US$21</td></tr><tr class="odd"><td>合計花費</td><td>≈ -NT$31.70</td></tr></tbody></table><h1 id="細節">細節</h1><h2 id="申請綁定約定帳戶">申請綁定約定帳戶</h2><p>需要的東西有：身分證、郵局存摺、印章和 Firstrade的帳戶資訊。這個過程大概需要 5 分鐘。</p><p>到郵局後，會給你一張紙填寫，基本上就照著 Firstrade給的資料填就好了。可以參考下面這張照片。（抱歉這種小朋友字體。）</p><figure><img src="/assets/PostToFirstrade/OutwardRemittanceForm.jpeg"alt="郵局約定表格" /><figcaption aria-hidden="true">郵局約定表格</figcaption></figure><p>不建議直接照抄（因為我字很醜），要抄還是照著 Firstrade的資料抄。或是參考網路上的教學，例如<ahref="https://george-dewi.com/firstrade/#t-1688828552566">這篇</a>。</p><h2 id="郵局匯款">郵局匯款</h2><p>大概等 2 天之後，就會收到郵局的簡訊通知。簡訊內容大概是這樣：</p><blockquote><p>中華郵政客戶您好：您申請網路（行動）郵局外匯匯出匯款服務已生效，請登入網路郵局或下載行動郵局APP，即可使用相關功能。</p></blockquote><p>我是用 <strong>行動郵局 App</strong>來轉帳的。一開始還以為是在一般的轉帳的地方，結果他是要去 App下面的「更多」→「外匯匯款」→「匯出匯款」才有。匯出的教學網路上一定也很多，要注意的就是要寫對附言。寫錯就麻煩了（我也沒遇過就是了XD）。</p><p>因為我是在活動期間，所以手續費只要 168。下面是匯款紀錄。</p><figure><img src="/assets/PostToFirstrade/PostRecord.png" alt="匯款紀錄" /><figcaption aria-hidden="true">匯款紀錄</figcaption></figure>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;tldr&quot;&gt;TL;DR&lt;/h1&gt;
&lt;p&gt;從郵局匯款到
Fristrade，綁定約定到入帳最快可能可以&lt;strong&gt;四天完成&lt;/strong&gt;。兩天是綁定的時間，兩天是匯款的時間。郵局這邊的手續費因為活動期間，用行動郵局
App 轉帳只要 168。之後最便宜應該也要 &lt;a
href=&quot;https://www.post.gov.tw/post/internet/B_saving/index.jsp?ID=3020204&quot;&gt;300
+ 100&lt;/a&gt;。&lt;strong&gt;中轉行收 15 USD&lt;/strong&gt;。&lt;/p&gt;</summary>
    
    
    
    <category term="Investment" scheme="https://blog.arui.dev/categories/Investment/"/>
    
    
    <category term="Life" scheme="https://blog.arui.dev/tags/Life/"/>
    
  </entry>
  
  <entry>
    <title>[OS] Chapter 12 — Mass Storage System</title>
    <link href="https://blog.arui.dev/[OS]Chapter-12/"/>
    <id>https://blog.arui.dev/[OS]Chapter-12/</id>
    <published>2022-01-31T10:12:24.000Z</published>
    <updated>2022-02-01T14:16:21.801Z</updated>
    
    <content type="html"><![CDATA[<div class="note default"><p><ahref="https://arui-tw.notion.site/Chapter-12-Mass-Storage-System-0a7b775db2304a7c88922dc8457ade4a">Notion好讀版</a></p></div><aside><p>✏️ 泛指所有 secondary storage</p></aside><h1 id="disk-structure">Disk Structure</h1><p>由磁盤組成，最小儲存單位是 sector，買來就切死的，所以用軟體的 block（多個 sector）來控制。Sector 會有number，所以可以對特定資料作讀取。</p><p><img src="/assets/%5BOS%5DChapter-12/Untitled.png" /></p><h2 id="sectors-per-track"><strong>Sectors per Track</strong></h2><ul><li>Constant linear velocity ****(CLV)<ul><li><p>Density of bits per track 是固定的</p></li><li><p>這樣內圈的資料量就會小於外圈的</p></li><li><p>但是這樣讀取資料的速度會不固定</p><p>→ 讀內圈要轉比較快</p></li><li><p>applications: CD-ROM and DVD-ROM</p></li></ul></li><li>Constant angular velocity ****(CAV)<ul><li>keep same rotation speed</li><li>內圈 density 比較高</li><li>這樣轉速就不用改</li><li>applications: hard disks</li></ul></li></ul><h2 id="disk-io">Disk IO</h2><p><img src="/assets/%5BOS%5DChapter-12/Untitled%201.png" /></p><ul><li>EIDE, ATA, SATA (Serial ATA), USB, SCSI, etc</li><li>效能會有差</li><li>I/O bus is controlled by controller</li></ul><span id="more"></span><h1 id="disk-scheduling">Disk Scheduling</h1><ul><li><p>Disk-access time has 3 major components</p><p><img src="/assets/%5BOS%5DChapter-12/Untitled%202.png" /></p><ul><li><p><strong>seektime</strong>：去移動讀寫頭的位置花的時間（通常最慢）</p><p>→ 主要優化目標</p></li><li><p>rotational latency：轉動磁盤的時間（快到可以被 ignore）</p></li><li><p>read time：content transfertime（取決於一次讀寫的資料量，也可能這邊最慢）</p></li></ul></li><li><p>Disk bandwidth — # of bytes transferred/(complete of last req –start of first req)</p></li></ul><h2 id="fcfs-first-come-first-served">FCFS(First-Come-First-Served)</h2><ul><li>問題的描述方式會是一串數字，代表著他是第幾圈的資料。</li></ul><p><img src="/assets/%5BOS%5DChapter-12/Untitled%203.png" /></p><h2 id="sstf-shortest-seek-time-first">SSTF(Shortest-Seek-Time-First)</h2><ul><li>看哪一個離目前的磁頭最近的就去那個（Greedy）</li><li>有 starvation，因為 request會不停地發生，所以很遠的可能一直被插隊</li><li>不是Optimal，因為只能找現在離我最近的，可能等一下進來的會更近，但是他就跳走了，他應該要停一下等那個未來的傢伙。</li></ul><p><img src="/assets/%5BOS%5DChapter-12/Untitled%204.png" /></p><h2 id="scan-scheduling">SCAN Scheduling</h2><ul><li><p>通常的解</p></li><li><p>我就移動我的，有剛好可以做的我就做</p></li><li><p>disk head move from one end to the other end</p></li><li><p>轉到底會換方向</p><p>⇒ 檢查時間不 uniform</p></li><li><p>A.k.a elevator algorithm</p></li></ul><figure><img src="/assets/%5BOS%5DChapter-12/Untitled%205.png"alt="注意他甚至會走到 0 的位置" /><figcaption aria-hidden="true">注意他甚至會走到 0 的位置</figcaption></figure><h2 id="c-scan-scheduling">C-SCAN Scheduling</h2><ul><li><p>只轉一個方向，走到底就把磁頭拉回去另一端</p><p>⇒ 比較 Uniform</p></li><li><p>（Round robin）</p></li><li><p>基本上都用這個，不會用 SCAN</p></li></ul><p><img src="/assets/%5BOS%5DChapter-12/Untitled%206.png" /></p><h2 id="c-look-scheduling">C-LOOK Scheduling</h2><ul><li>一樣只轉一個方向，但是不會走到底</li><li>如果往右邊走，就會去看右邊的下一個是誰</li><li>其實跟 SSTF 很像，因為他在也會被剛進來的帶著走（但是不會starvation）</li></ul><p><img src="/assets/%5BOS%5DChapter-12/Untitled%207.png" /></p><h2 id="summary">Summary</h2><ul><li>SSTF<ul><li>common and has a natural appeal, but not optimal</li></ul></li><li>SCAN<ul><li>perform better for disks with <strong>heavy load</strong></li><li><strong>No</strong> starvation problem</li></ul></li><li>C-SCAN<ul><li>More uniform wait time</li></ul></li><li>Performance is also influenced by the file-allocation method<ul><li><p>Contiguous: less head movement</p><p>→ 可能會因為有同時很多 process 在讀，所以還是不 contiguous的</p></li><li><p>Indexed &amp; linked: greater head movement</p></li></ul></li></ul><h2 id="review-slides-i">Review Slides (I)</h2><ul><li>3 major components in disk-access time<ul><li>Seek</li><li>Rotation</li><li>Read</li></ul></li><li>Goal of disk-scheduling algorithm</li><li>Disk-scheduling algorithms<ul><li>FCFS</li><li>SSTF</li><li>SCAN</li><li>C-SCAN</li><li>C-LOOK</li></ul></li></ul><h1 id="disk-swap-space-management">Disk &amp; Swap-SpaceManagement</h1><h2 id="disk-formatting">Disk Formatting</h2><p>一般的格式化是 high level 的格式化，low level 的 disk 的formatting（這是出廠前就做好的）是 dividing a disk (magnetic recordingmaterial) into sectors that disk controller can read and write 。</p><ul><li>each sector = header + data area + trailer<ul><li>Header — metadata，i.e. where the sector is, the ID of thesector</li><li>trailer — error correction code, based on all bytes in dataarea</li></ul></li><li>High-level: partition and 用 data block 的方式去存取</li></ul><h2 id="booting">Booting</h2><ul><li><p>Bootstrap program</p><ul><li><p>Initialize CPU, registers, device controllers, memory, and thenstarts OS</p></li><li><p>First <strong>bootstrap code</strong> stored in ROM</p></li><li><p>Complete bootstrap in the boot block the boot disk (aka systemdisk)</p></li></ul></li><li><p>Booting from a Disk in Windows 2000</p><p><img src="/assets/%5BOS%5DChapter-12/Untitled%208.png" /></p><ol type="1"><li>Run bootstrap code in ROM</li><li>Read boot code in MBR(Master boot record)</li><li>Find boot partition from partition table</li><li>Read boot sector/block and continue booting</li></ol></li></ul><h2 id="bad-block">Bad block</h2><p>A.k.a 壞軌</p><ul><li>Disk controller 是第一個去處理的</li><li>IDE — 看 ECC 知道他壞掉就不會讀給上面的，而是 notify他們說「欸，壞去啊！」</li><li>SCSI — 除了不會讓你用以外，還會把壞掉的地方的儲存空間 recreate出來，有下面兩種方式<ol type="1"><li><p>Sector sparing (forwarding) —像是有空白的撲克牌，有牌不見就拿空的補充。但是這樣連續的 sector #會存在不連續的地方，所以壞太多效能就會變差。</p><p>→ Run time 在用的</p></li><li><p>Sector slipping — 從壞掉的地方開始全部往後移一格。超花時間。</p><p>→ Reboot 在做的</p></li></ol></li></ul><h2 id="swap-space">Swap space</h2><ul><li><ahref="https://hackmd.io/@Pl-eQT9CQaS0jhExKqL8_w/BkhOSR4jW/https%3A%2F%2Fhackmd.io%2Fs%2FryDbZPA7f#Swap-space">Seethis</a></li><li>之前是說由 Virtual Memory 或是 Memory Manager 。把他切成固定的page，然後直接 map。</li><li>他也可以用 File system 來管。把每一個 page 設成 4kb 的file。當要存取的時候就用 file name 當作 page ID。</li><li>通常是直接用 Memory Manager 來操作，不通過 filesystem，比較快。</li><li>所以用 raw partition 一定比較快，但是這樣就會浪費 raw partition的空間。且如果 VM 用得很兇，那 swap space會不夠，那就效能大量下降。</li><li>所以通常都一起用。</li><li>Swap Space Allocation<ul><li>1st version: disk 和 memory 都一份一樣的</li><li>2nd version:<ul><li>Solaris 1:<ul><li>Run time 產生的才存，像是 code 就不用存，反正需要再去 disk拿就好</li><li>如果 declare 了但是還沒用，那就不用存在 swap space</li></ul></li><li>Solaris 2:<ul><li>先不要再 swap space 存 copy，只有在 swap out 才 create</li></ul></li></ul></li></ul></li></ul><p><img src="/assets/%5BOS%5DChapter-12/Untitled%209.png" /></p><h1 id="raid-structure">RAID Structure</h1><p>現在儲存空間越來越便宜。</p><p>RAID = <strong>R</strong>edundant <strong>A</strong>rrays of<strong>I</strong>nexpensive <strong>D</strong>isks</p><p>→ 想要用很多便宜的硬碟，產生一個 powerful 的 storage device</p><p>→ provide <strong>reliability</strong> via<strong>redundancy</strong> (多 backup)</p><p>→ improve <strong>performance</strong> via<strong>parallelism</strong> (平行化，一起讀寫)</p><ul><li>RAID is arranged into different levels<ul><li>Striping → 資料分散</li><li>Mirror (Replication) → 資料 copy</li><li>Error-correcting code (ECC) &amp; Parity bit</li></ul></li></ul><h2 id="raid-0">RAID 0</h2><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2010.png" /></p><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2011.png" /></p><ul><li>Striping → 把檔案切割用 Round Robin 的方式擺到印碟上去</li><li>Improve <strong>performance</strong> via<strong>parallelism</strong> → 大資料可以同時讀取</li></ul><h2 id="raid-1">RAID 1</h2><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2012.png" /></p><ul><li>Mirror → 複製</li><li>Provide <strong>reliability</strong> via <strong>redundancy</strong>→ 通常最多作三個 replica<ul><li>讀取速度會變成 N 倍</li><li>寫入速度不變</li></ul></li></ul><h2 id="raid-2-hamming-code">RAID 2: Hamming code</h2><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2013.png" /></p><ul><li><p><a href="http://en.wikipedia.org/wiki/Hamming_code">Hammingcode</a> → 可以推出是誰遺失然後重建出來</p></li><li><p>E.g.: Hamming code(7,4)</p><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2014.png" /></p><ul><li>4 data bits (on 4 disks) + 3 parity bits (on 3 disks)</li><li>只浪費的 75%（RAID 1 是 100%）</li></ul></li></ul><h2 id="raid-3-4-parity-bit">RAID 3 &amp; 4: Parity Bit</h2><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2015.png" /></p><ul><li><p>硬碟壞掉，他本來就會自己說，所以應該是不用偵測的，我們只需要recovery</p><p>→ a single parity bit is enough to correct error from a single diskfailure</p><p>→ 所以我們只需要浪費 <code>1/N</code></p></li><li><p>RAID3: Bit-level striping; RAID 4: Block-level striping</p><p>→ RAID 4 recover 的速度會略快（除非壞掉的只有一個bit），因為讀取都是一個 block 在操作的，所以他就不用橫跨好幾的 disk了</p></li><li><p>讀取速度是 <code>N - 1</code> 倍，寫入速度不變（因為要去寫存Parity bit 的那顆）</p></li></ul><h2 id="raid-5-distributed-parity">RAID 5: Distributed Parity</h2><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2016.png" /></p><ul><li>Load balancing → 把 parity bit 分散在各個 disk</li><li>最常見的</li><li>Read 可以是 <code>N</code> 倍了</li><li>Write<ul><li><p>Method 1</p><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2017.png" /></p><ol type="1"><li>讀 N-2 筆 data</li><li>重算 pb</li><li>寫進去那兩個</li></ol><p>⇒ N / (N - 2 + 2) = 1</p></li><li><p>Method 2</p><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2018.png" /></p><ol type="1"><li>讀原本的值</li><li>算出修改的影響</li><li>寫入</li></ol><p>⇒ N / 4 times faster</p></li></ul></li></ul><h2 id="raid-6-pq-dual-parity-redundancy">RAID 6: P+Q Dual ParityRedundancy</h2><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2019.png" /></p><ul><li>你有不只一個 PB ⇒ 可以多個硬碟壞掉</li></ul><h2 id="hybrid-raid">Hybrid RAID</h2><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2020.png" /></p><ul><li>RAID 0+1: Stripe then replicate → 保護能力比較弱</li><li>RAID 1+0: Replicate then stripe</li><li>先寫先做</li></ul><h2 id="review-slides-ii">Review Slides (II)</h2><ul><li>Swap space using FS? Raw partition?</li><li>How to reduce swap space usage?</li><li>RAID disks? Purpose?</li><li>RAID-0~6?</li><li>RAID 0+1, RAID 1+0</li></ul><h1 id="textbook-questions">Textbook Questions</h1><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2021.png" /></p><p><img src="/assets/%5BOS%5DChapter-12/Untitled%2022.png" /></p><div class="note warning"><p>此筆記為清華大學周志遠教授作業系統之課堂筆記，所有內容及圖片皆取材於課堂內容。<br />如內容有誤，歡迎來信 <ahref="mailto:mail@arui.dev">mail@arui.dev</a>。</p></div>]]></content>
    
    
    <summary type="html">&lt;div class=&quot;note default&quot;&gt;&lt;p&gt;&lt;a
href=&quot;https://arui-tw.notion.site/Chapter-12-Mass-Storage-System-0a7b775db2304a7c88922dc8457ade4a&quot;&gt;Notion
好讀版&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;✏️ 泛指所有 secondary storage&lt;/p&gt;
&lt;/aside&gt;
&lt;h1 id=&quot;disk-structure&quot;&gt;Disk Structure&lt;/h1&gt;
&lt;p&gt;由磁盤組成，最小儲存單位是 sector，買來就切死的，所以用軟體的 block
（多個 sector）來控制。Sector 會有
number，所以可以對特定資料作讀取。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/%5BOS%5DChapter-12/Untitled.png&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;sectors-per-track&quot;&gt;&lt;strong&gt;Sectors per Track&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Constant linear velocity ****(CLV)
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Density of bits per track 是固定的&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;這樣內圈的資料量就會小於外圈的&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;但是這樣讀取資料的速度會不固定&lt;/p&gt;
&lt;p&gt;→ 讀內圈要轉比較快&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;applications: CD-ROM and DVD-ROM&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Constant angular velocity ****(CAV)
&lt;ul&gt;
&lt;li&gt;keep same rotation speed&lt;/li&gt;
&lt;li&gt;內圈 density 比較高&lt;/li&gt;
&lt;li&gt;這樣轉速就不用改&lt;/li&gt;
&lt;li&gt;applications: hard disks&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;disk-io&quot;&gt;Disk IO&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/assets/%5BOS%5DChapter-12/Untitled%201.png&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EIDE, ATA, SATA (Serial ATA), USB, SCSI, etc&lt;/li&gt;
&lt;li&gt;效能會有差&lt;/li&gt;
&lt;li&gt;I/O bus is controlled by controller&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Operating System Notes" scheme="https://blog.arui.dev/categories/Operating-System-Notes/"/>
    
    
    <category term="Operating System" scheme="https://blog.arui.dev/tags/Operating-System/"/>
    
    <category term="Notes" scheme="https://blog.arui.dev/tags/Notes/"/>
    
  </entry>
  
  <entry>
    <title>[OS] Chapter 13 — I/O System</title>
    <link href="https://blog.arui.dev/[OS]Chapter-13/"/>
    <id>https://blog.arui.dev/[OS]Chapter-13/</id>
    <published>2022-01-31T10:12:24.000Z</published>
    <updated>2022-02-01T14:20:34.498Z</updated>
    
    <content type="html"><![CDATA[<div class="note default"><p><ahref="https://www.notion.so/arui-tw/Chapter-13-I-O-System-7f1b37167d5b4a77bc4e18c96b74ed95">Notion好讀版</a></p></div><h1 id="overview">Overview</h1><ul><li><p>電腦不是在做 I/O 就是在做計算</p></li><li><p><strong>I/O devices</strong>: tape, HD, mouse, joystick, networkcard, screen, flash disks, etc</p></li><li><p><strong>I/O subsystem</strong>: the methods to <strong>controlall I/O devices</strong></p></li><li><p>Two conflicting trends</p><ul><li>我們希望他是 interface，這樣才可以 standardization 的控制</li><li>但是他又很多樣性</li></ul></li><li><p><strong>Device drivers</strong>: a uniform device-access<strong>interface</strong> to the I/O subsystem</p><p>⇒ Similar to system calls between apps and OS</p></li><li><p>Device categories</p><ul><li>Storage devices: disks, tapes</li><li>Transmission devices: network cards, modems</li><li>Human-interface devices: keyboard, screen, mouse</li><li>Specialized devices: joystick, touchpad</li></ul></li></ul><h1 id="io-hardware">I/O Hardware</h1><ul><li><p><strong>Port</strong>: A <strong>connection point</strong>between I/O devices and the host. 每個 port 都有自己的 ID，那就是 device對於電腦的 identifier。</p><p>→ E.g.: USB ports</p></li><li><p><strong>Controller</strong>: A collection of electronics that canoperate a port, a bus, or a device</p><p>⇒ A controller could have its own processor, memory, etc. (E.g.: SCSIcontroller)</p></li><li><p><strong>Bus</strong>: A set of <strong>wires and a well-definedprotocol</strong> that specifies messages sent over thewires（連接的方式，除了物理相接，還有 protocol 的部分）</p><p>→ E.g.: PCI bus</p></li></ul><span id="more"></span><p><img src="/assets/%5BOS%5DChapter-13/Untitled.png" /></p><p><img src="/assets/%5BOS%5DChapter-13/Untitled%201.png" /></p><h1 id="io-methods">I/O Methods</h1><ul><li>透過 <code>port address</code> 做 <code>什麼事</code></li><li>Port address 用一個簡單的 table 就好了，反正也沒有很大</li><li>Each I/O port consists of four registers (1~4 Bytes)<ul><li>Data-in register — In buffer</li><li>Data-out register — Out buffer</li><li>Status register — 狀態的值</li><li>Control register — command</li></ul></li></ul><h2 id="io-methods-categorization">I/O Methods Categorization</h2><ul><li><p>Depending on how to address a device</p><ul><li><p>Port-mapped I/O</p><ul><li>直接用 I/O instruction (e.g. <code>IN</code>, <code>OUT</code>)</li></ul></li><li><p>Memory-mapped I/O</p><ul><li>Access by standard data-transfer instruction (e.g.<code>MOV</code>)</li></ul><p>🙂 More efficient for <strong>large memory I/O</strong> (e.g. graphiccard)</p><p>☹️ Vulnerable to accidental modification, error</p></li></ul></li><li><p>Depending on how to interact with a device:</p><ul><li><p><strong>Poll</strong> (busy-waiting): processor periodicallycheck status register of a device.不停地確認好了沒，啥時可以作下一個</p><p>→ 如果量不多，用這個</p></li><li><p><strong>Interrupt</strong>: device notify processor of itscompletion. I/O 好了他會直接 call interrupt 跟你的程式講。</p></li></ul><p>⇒ 通常會 Memory-mapped I/O ＋ Interrupt或是另外兩個相加，不然會互相抵銷好處。</p></li><li><p>Depending on who to control the transfer:</p><ul><li><p><strong>Programmed I/O</strong>: transfer controlled by CPU</p><p>→ 需要一直用 CPU</p></li><li><p><strong>Direct memory access</strong> (DMA) I/O: controlled by<strong>DMA controller</strong> (a special purpose controller)</p><p>→ 只負責 I/O</p><ul><li>Design for <strong>large data transfer</strong></li></ul></li></ul></li></ul><h2 id="interrupt">Interrupt</h2><ul><li><p>Interrupt Vector Table</p><figure><img src="/assets/%5BOS%5DChapter-13/Untitled%202.png"alt="數字越小越重要" /><figcaption aria-hidden="true">數字越小越重要</figcaption></figure></li><li><p>Interrupt Prioritization</p><ul><li><p>Maskable interrupt — 有一些不重要的 interrupt 會被 mask掉</p></li><li><p>Non-maskable interrupt (NMI): highest-priority, never masked</p><p>→ Often used for power-down, memory error</p></li></ul></li><li><p>Interrupt-Driven I/O</p><p><img src="/assets/%5BOS%5DChapter-13/Untitled%203.png" /></p></li><li><p>CPU and device Interrupt handshake</p><ol type="1"><li>Device asserts <strong>interrupt request</strong> (IRQ) → I/O要註冊他的 interrupt，這樣 OS 才知道要去處理誰</li><li>CPU checks the <strong>interrupt request line</strong> at thebeginning of each instruction cycle</li><li>Save the status and address of interrupted process</li><li>CPU acknowledges the interrupt and search the <strong>interruptvector</strong> table for interrupt handler routines</li><li>CPU fetches the next instruction from the <strong>handlerroutine</strong></li><li>Restore interrupted process after executing interrupt handlerroutine</li></ol></li></ul><h2 id="dma-direct-memory-access">DMA (Direct Memory Access)</h2><p><img src="/assets/%5BOS%5DChapter-13/Untitled%204.png" /></p><p>File System → （我要讀多少資料，要讀到 X）→ device driver →（說「我要讀多少資料，要讀到 X」，並 register 一個 interrupt說「做完之後跟我說欸」） → disk controller → （初始化DMA，因為他只能傳很少的資料，所以 DMA 就開始不停地送搬移的指令到 diskcontroller，然後存到 X）→ DMA → （Through interrupt 到 CPU 說我搬完了）→CPU → 看到搬完了，開心：）</p><p>注意那個 X 通常是 physical 的 address，不然就要去看 pagetable，那就需要 CPU 去跑 OS 來看。</p><p>→ 這樣 Virtual Memory 就有點失效，因為那塊就被 fix 住了。</p><h2 id="review-slides-i">Review Slides ( I )</h2><ul><li>Definition of I/O port? Bus? Controller?</li><li><strong>I/O device and CPU communication?</strong><ul><li><strong>Port-mapped vs. Memory-mapped</strong></li><li><strong>Poll vs. Interrupt</strong></li><li><strong>Programmed I/O vs. DMA</strong></li></ul></li><li>Steps to handle an interrupt I/O and DMA request?</li></ul><h1 id="kernel-io-subsystem">Kernel I/O Subsystem</h1><ul><li><p><strong>I/O Scheduling</strong></p></li><li><p><strong>Buffering — Bridge 速差</strong></p></li><li><p><strong>Caching —</strong> Always just a copy; Key toperformance</p></li><li><p><strong>Spooling — 像 buffer，但是是 all ornothing</strong></p></li><li><p><strong>Error handling —</strong> when I/O error happens</p></li><li><p><strong>I/O protection —</strong> Privilegedinstructions</p></li><li><p>Device-status Table</p><p><img src="/assets/%5BOS%5DChapter-13/Untitled%205.png" /></p></li><li><p>Life Cycle of An I/O Request</p><p><img src="/assets/%5BOS%5DChapter-13/Untitled%206.png" /></p></li></ul><h1 id="performance">Performance</h1><ul><li>Intercomputer Communications</li></ul><h1 id="application-interface">Application Interface</h1><h1 id="textbook-questions">Textbook Questions</h1><p><img src="/assets/%5BOS%5DChapter-13/Untitled%207.png" /></p><p><img src="/assets/%5BOS%5DChapter-13/Untitled%208.png" /></p><div class="note warning"><p>此筆記為清華大學周志遠教授作業系統之課堂筆記，所有內容及圖片皆取材於課堂內容。<br />如內容有誤，歡迎來信 <ahref="mailto:mail@arui.dev">mail@arui.dev</a>。</p></div>]]></content>
    
    
    <summary type="html">&lt;div class=&quot;note default&quot;&gt;&lt;p&gt;&lt;a
href=&quot;https://www.notion.so/arui-tw/Chapter-13-I-O-System-7f1b37167d5b4a77bc4e18c96b74ed95&quot;&gt;Notion
好讀版&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id=&quot;overview&quot;&gt;Overview&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;電腦不是在做 I/O 就是在做計算&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;I/O devices&lt;/strong&gt;: tape, HD, mouse, joystick, network
card, screen, flash disks, etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;I/O subsystem&lt;/strong&gt;: the methods to &lt;strong&gt;control
all I/O devices&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Two conflicting trends&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我們希望他是 interface，這樣才可以 standardization 的控制&lt;/li&gt;
&lt;li&gt;但是他又很多樣性&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Device drivers&lt;/strong&gt;: a uniform device-access
&lt;strong&gt;interface&lt;/strong&gt; to the I/O subsystem&lt;/p&gt;
&lt;p&gt;⇒ Similar to system calls between apps and OS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Device categories&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage devices: disks, tapes&lt;/li&gt;
&lt;li&gt;Transmission devices: network cards, modems&lt;/li&gt;
&lt;li&gt;Human-interface devices: keyboard, screen, mouse&lt;/li&gt;
&lt;li&gt;Specialized devices: joystick, touchpad&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;io-hardware&quot;&gt;I/O Hardware&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Port&lt;/strong&gt;: A &lt;strong&gt;connection point&lt;/strong&gt;
between I/O devices and the host. 每個 port 都有自己的 ID，那就是 device
對於電腦的 identifier。&lt;/p&gt;
&lt;p&gt;→ E.g.: USB ports&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Controller&lt;/strong&gt;: A collection of electronics that can
operate a port, a bus, or a device&lt;/p&gt;
&lt;p&gt;⇒ A controller could have its own processor, memory, etc. (E.g.: SCSI
controller)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bus&lt;/strong&gt;: A set of &lt;strong&gt;wires and a well-defined
protocol&lt;/strong&gt; that specifies messages sent over the
wires（連接的方式，除了物理相接，還有 protocol 的部分）&lt;/p&gt;
&lt;p&gt;→ E.g.: PCI bus&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Operating System Notes" scheme="https://blog.arui.dev/categories/Operating-System-Notes/"/>
    
    
    <category term="Operating System" scheme="https://blog.arui.dev/tags/Operating-System/"/>
    
    <category term="Notes" scheme="https://blog.arui.dev/tags/Notes/"/>
    
  </entry>
  
  <entry>
    <title>[OS] Chapter 11 — File System Implementation</title>
    <link href="https://blog.arui.dev/[OS]Chapter-11/"/>
    <id>https://blog.arui.dev/[OS]Chapter-11/</id>
    <published>2022-01-31T10:11:24.000Z</published>
    <updated>2022-02-01T14:14:53.533Z</updated>
    
    <content type="html"><![CDATA[<div class="note default"><p><ahref="https://arui-tw.notion.site/Chapter-11-File-System-Implementation-3bd2f7997ad041ac8966f8bd52fd1b18">Notion好讀版</a></p></div><h1 id="file-system-structure">File-System Structure</h1><ul><li>一個 disk 提供的最小單位是 sectors（usually 512 bytes）</li><li>但是 mapping 的時候不喜歡用 sector，太小了</li><li>所以都用 Blocks，通常是四到十幾個 sectors</li><li>一個 OS 可以 support &gt; 1 個 FS type</li><li>需要兩個 interface<ul><li>對上：user programs</li><li>對下：physical storage (disk)</li></ul></li></ul><h2 id="layered-file-system">Layered File System</h2><ul><li>最上層是 API</li><li>最下層（最終要寫到 disk 上面去的）要透過 driver 寫過去，那 driver要的是單位是 sector</li><li>Logical file system — 根據 file path 找到 fileID，也要去判斷權限（i.e. 判斷 API 是不是合法可執行的東西）</li><li>File-organization module — 每一個 FS 最不一樣的地方。要找到在logical 中的位址對應到的 physical 的地方。（甚至需要 map到不同的電腦）</li><li>Basic File system — 最基本的 I/O 的動作（跟檔案管理無關啦）</li></ul><figure><img src="/assets/%5BOS%5DChapter-11/Untitled.png"alt="右邊的名詞不用記" /><figcaption aria-hidden="true">右邊的名詞不用記</figcaption></figure><ul><li><p>之所以一個 <code>fread</code> 可以對不同的 file system作操作就是中間有 FS manager (VFS — Virtual File System)</p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%201.png" /></p></li></ul><span id="more"></span><h1 id="file-system-implementation">File System Implementation</h1><h2 id="on-disk-structure">On-Disk Structure</h2><p>→ 因為 reboot 後，資料還是要在，所以和之前的不一樣</p><ul><li>Boot control <strong>block</strong> ****(per partition) — 關於booting 的 code 或資訊<ul><li>裝 OS 他就會幫你 create 起來</li><li>一個 partition 只會有一個（也最多一個） boot controlblock，通常會放在最上面</li><li>如果不是開機槽，那就不會有這個 block</li><li>Unix File System → boot block; NTFS → partition boot sector</li></ul></li><li>Partition control block ****(per partition) — 關於這個 partition的資訊<ul><li>details: # of blocks, block size, free-block-list, free FCBpointers, etc</li><li>UFS → superblock; NTFS → Master File Table</li><li>如果沒有 boot control block，那他應該會在最前面</li></ul></li><li>File control block (per file) — file 的 metadata<ul><li>注意不存 data，data 會有一個指標指過去</li><li>UFS — <strong>inode</strong>; NTFS: stored in MFT (relationaldatabase)</li></ul></li><li>Directory structure (per file system): organize files</li></ul><p><img src="/assets/%5BOS%5DChapter-11/Untitled%202.png" /></p><ul><li><p><code>$ stat</code></p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%203.png" /></p></li></ul><h2 id="in-memory-structure">In-Memory Structure</h2><p>→ 一樣的，只是哪些東西要被 load 到 memory 裡面</p><ul><li>in-memory partition table — 有人被 mount，他就會存關於這個 partition的資訊。Unmount 就會被移除。</li><li>in-memory directory structure — 最近 accessed 到的 directory</li><li>system-wide open-file table — 被 open 的 file 的 file controlblock</li><li>per-process open-file table — process 對於一個 file 需要 keep的資訊，且 file close 的時候，他就會被清掉，不會寫回去。</li></ul><p><strong>File-Open</strong></p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%204.png" /></p><ul><li>如果沒讀過這個 directory，他就會去 disk （secondarystorage）的地方把他拉出來</li><li>Directory 的最後接的是 file control block</li></ul><p><strong>File-Read</strong></p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%205.png" /></p><ul><li>上面 open 好了，所以兩個 open-file table 都 ready 了</li></ul><ol type="1"><li>去 per-process 確認有沒有權限（logical file system）</li><li>如果有，去 system-wide 找 file control block 裡面存的 data block 的pointer</li></ol><p><strong>File-Create</strong></p><ol type="1"><li>OS allocates a new FCB</li><li>Update directory structure<ol type="1"><li>OS read in the corresponding directory structure into memory</li><li><strong>Updates the dir structure</strong> with the new file nameand the FCB</li><li>(After file being closed), OS writes back the directory structureback to disk → Close 才會寫回去，因為 disk 太慢了</li></ol></li><li>The file appears in user’s dir command</li></ol><h2 id="virtual-file-system">Virtual File System</h2><ul><li>Four main object types defined by Linux VFS Disk Allocation Methods<ul><li>inode (FCB) → an individual <strong>file</strong></li><li>file object → an <strong>open file</strong> (per process)</li><li>superblock object → an entire file system</li><li>entry object → an individual directory entry</li></ul></li></ul><h2 id="directory-implementation"><strong>DirectoryImplementation</strong></h2><p>大型系統的 directory 太大了，且掉了很慘</p><ul><li>Linear lists<ul><li>use link list and traverse</li><li>easy to program but poor performance</li></ul></li><li>Hash table<ul><li>把 file path 當成 key，FCB 是 value</li><li>constant time for searching</li><li>linked list for collisions on a hash entry</li><li>hash table usually has fixed # of entries</li></ul></li></ul><h2 id="review-slides-i">Review Slides (I)</h2><ul><li>Transfer unit between memory and disk?</li><li>App → LFS → FOM → BFS → I/O Control → Devices</li><li>on-disk structure<ul><li>Boot control block, Partition control block</li><li>File control block, Directory structure</li></ul></li><li>In-memory<ul><li>Partition table, Directory structure</li><li>System-wide open-file table</li><li>Per-process open-file table</li></ul></li><li>Steps to open file, read/write file and create file?</li><li>Purpose of VFS?</li></ul><h1 id="allocation-methods">Allocation Methods</h1><p>把 file 對應到 block。</p><h2 id="contiguous-allocation">Contiguous Allocation</h2><figure><img src="/assets/%5BOS%5DChapter-11/Untitled%206.png"alt="右邊的表，每一行就是一個 inode，start 和 length 是 metadata" /><figcaption aria-hidden="true">右邊的表，每一行就是一個 inode，start 和length 是 metadata</figcaption></figure><ul><li>一個 block 一定只屬於一個 file</li><li>Sequential access 和 random access 都很有效率（根據 I/O的次數作判斷）→ random 是因為可以用算的飛過去</li><li>☹️ Problems<ul><li>External fragmentation → compaction（硬碟清理）</li><li>File cannot grow（會被後面卡住）→ 搬移資料（big cost）</li></ul></li></ul><h2 id="extent-based-file-system-ext">Extent-Based File System(Ext)</h2><ul><li>用 link list 的方法把 extent 串起來</li><li>所以除了存 start 和 length，還要多存 pointer to next extent</li><li>☹️ Problems<ul><li>Random access become more costly</li><li>“Internal fragmentation” → extent 給他的 blocks 沒用完</li></ul></li></ul><h2 id="linked-allocation">Linked Allocation</h2><p><img src="/assets/%5BOS%5DChapter-11/Untitled%207.png" /></p><ul><li>把下一個 block 的 pointer 存在 data block 裡面，dir 只會有第一個pointer</li><li>Only good for <strong>sequential-access</strong> files, randomaccess need to traverse through the link list</li><li>Each access to a link list is a disk I/O (because link pointer isstored inside the data block)</li><li>每一個 data block 都會浪費 4 byte 去存 pointer</li><li>Reliability → 斷了就 GG</li></ul><h2 id="fat-file-allocation-table-file-system">FAT (File AllocationTable) file system</h2><p><img src="/assets/%5BOS%5DChapter-11/Untitled%208.png" /></p><ul><li>把整個 pointers 存起來，所以就變成一個純 link list，存取還是需要traverse，但是不用 I/O，只會有很快的 memory access</li><li>超快，但是需要空間</li><li>Link 斷了也 GG</li></ul><h2 id="indexed-allocation">Indexed Allocation</h2><p><img src="/assets/%5BOS%5DChapter-11/Untitled%209.png" /></p><ul><li>跟剛剛很像，但是他是用 index，不用 traverse</li><li>很快，random 也超快</li><li>注意那個 index 也是存在 disk 上了，他也是一個 block</li><li>所以 inode 會存那個 index 在的 block</li><li>☹️<ul><li>Index block 很浪費空間，小的 block 根本用不完</li><li>Index block 如果不夠大？<ul><li><p>Linked Indexed Scheme</p><p>→ search time 會變長</p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%2010.png" /></p></li><li><p>Multilevel Scheme (two-level)</p><p>→ 大 file 這個比較優</p><p>→ 小 file 就很浪費</p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%2011.png" /></p></li></ul></li></ul></li></ul><h2 id="combined-scheme-unix-inode">Combined Scheme: Unix inode</h2><p>根據 file size 決定用哪個</p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%2012.png" /></p><h1 id="free-space-management">Free-Space Management</h1><ul><li>找到全部的 free block</li><li>Free-space list: records all free disk blocks</li><li>Scheme<ul><li><p>Bit vector</p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%2013.png" /></p><ul><li>用一串 1 和 0 去紀錄他是不是 free 的</li><li>🙂 simplicity, efficient</li><li>☹️ 因為是 fix size，會浪費 memory 空間</li></ul></li><li><p>Linked list (same as linked allocation)</p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%2014.png" /></p></li><li><p>Grouping (same as linked index allocation)</p></li><li><p>Counting (same as contiguous allocation)</p><p>→ keep the address of the first free block and # of contiguous freeblocks</p></li></ul></li></ul><h2 id="review-slides-ii">Review Slides (II)</h2><ul><li>Allocation:<ul><li>Contiguous file allocation? Extent-based file system?</li><li>Linked allocation?</li><li>Indexed allocation?<ul><li>Linked scheme</li><li>multilevel index allocation</li><li>Combine scheme</li></ul></li></ul></li><li>Free space:<ul><li>Bit vector, linked list, counting, grouping</li></ul></li></ul><h1 id="textbook-questions">Textbook Questions</h1><p><img src="/assets/%5BOS%5DChapter-11/Untitled%2015.png" /></p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%2016.png" /></p><p><img src="/assets/%5BOS%5DChapter-11/Untitled%2017.png" /></p><div class="note warning"><p>此筆記為清華大學周志遠教授作業系統之課堂筆記，所有內容及圖片皆取材於課堂內容。<br />如內容有誤，歡迎來信 <ahref="mailto:mail@arui.dev">mail@arui.dev</a>。</p></div>]]></content>
    
    
    <summary type="html">&lt;div class=&quot;note default&quot;&gt;&lt;p&gt;&lt;a
href=&quot;https://arui-tw.notion.site/Chapter-11-File-System-Implementation-3bd2f7997ad041ac8966f8bd52fd1b18&quot;&gt;Notion
好讀版&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id=&quot;file-system-structure&quot;&gt;File-System Structure&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;一個 disk 提供的最小單位是 sectors（usually 512 bytes）&lt;/li&gt;
&lt;li&gt;但是 mapping 的時候不喜歡用 sector，太小了&lt;/li&gt;
&lt;li&gt;所以都用 Blocks，通常是四到十幾個 sectors&lt;/li&gt;
&lt;li&gt;一個 OS 可以 support &amp;gt; 1 個 FS type&lt;/li&gt;
&lt;li&gt;需要兩個 interface
&lt;ul&gt;
&lt;li&gt;對上：user programs&lt;/li&gt;
&lt;li&gt;對下：physical storage (disk)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;layered-file-system&quot;&gt;Layered File System&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;最上層是 API&lt;/li&gt;
&lt;li&gt;最下層（最終要寫到 disk 上面去的）要透過 driver 寫過去，那 driver
要的是單位是 sector&lt;/li&gt;
&lt;li&gt;Logical file system — 根據 file path 找到 file
ID，也要去判斷權限（i.e. 判斷 API 是不是合法可執行的東西）&lt;/li&gt;
&lt;li&gt;File-organization module — 每一個 FS 最不一樣的地方。要找到在
logical 中的位址對應到的 physical 的地方。（甚至需要 map
到不同的電腦）&lt;/li&gt;
&lt;li&gt;Basic File system — 最基本的 I/O 的動作（跟檔案管理無關啦）&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img src=&quot;/assets/%5BOS%5DChapter-11/Untitled.png&quot;
alt=&quot;右邊的名詞不用記&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;右邊的名詞不用記&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;之所以一個 &lt;code&gt;fread&lt;/code&gt; 可以對不同的 file system
作操作就是中間有 FS manager (VFS — Virtual File System)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/%5BOS%5DChapter-11/Untitled%201.png&quot; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Operating System Notes" scheme="https://blog.arui.dev/categories/Operating-System-Notes/"/>
    
    
    <category term="Operating System" scheme="https://blog.arui.dev/tags/Operating-System/"/>
    
    <category term="Notes" scheme="https://blog.arui.dev/tags/Notes/"/>
    
  </entry>
  
  <entry>
    <title>[OS] Chapter 10 — File System Interface</title>
    <link href="https://blog.arui.dev/[OS]Chapter-10/"/>
    <id>https://blog.arui.dev/[OS]Chapter-10/</id>
    <published>2022-01-31T10:10:24.000Z</published>
    <updated>2022-02-01T14:22:32.828Z</updated>
    
    <content type="html"><![CDATA[<div class="note default"><p><ahref="https://arui-tw.notion.site/Chapter-10-File-System-Interface-588a7531b9aa40058c8423706f01da16">Notion好讀版</a></p></div><aside><p>✏️ 從使用者的角度去看</p></aside><h1 id="file-concept">File Concept</h1><p>File 也是抽像的概念。</p><aside><p>📖 <strong>File (Data)</strong>: a logical storage unit created byOS</p></aside><ul><li><p>Physical storage unit in disk</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled.png" /></p></li><li><p>File attributes (Metadata)</p><ul><li>Identifier: non-human-readable name</li><li>Name</li><li>Type</li><li>Location</li><li>Size</li><li><strong>Protection</strong></li><li>Last-access time, Last-updated time</li></ul></li><li><p>File operations</p><ul><li>Create</li><li>Write</li><li>Read</li><li>Repositioning within a file (i.e. file seek)</li><li>Delete</li><li>Truncating → 切掉尾巴</li><li>Appending → 貼在尾巴 <span id="more"></span></li></ul></li><li><p>Open-File Tables</p><p>注意他存的是 metadata，不是 data</p><ul><li>Per-process table<ul><li><p>Tracking all files opened by this process</p></li><li><p>跟操作這個 file 有關的資訊（independent 的）</p></li><li><p>File pointer → process 操作這個檔案到的位置</p></li><li><p>裡面還有一個 pointer 指到 file 的 System-wide table</p><p>⇒ 這樣就可以避免資料一致性的問題，所以才不要 duplicate 一份到Per-process table 裡面</p></li></ul></li><li>System-wide table ****<ul><li>不管誰操作都要看到的資訊（share 的）</li><li>File size, disk location</li></ul></li></ul><p><img src="/assets/%5BOS%5DChapter-10/Untitled%201.png" /></p></li><li><p>Open File Attributes</p><ul><li>File pointer (per-process)</li><li>File open count (system table)</li><li>Disk location (system table)</li><li>Access rights (per-process)</li></ul></li><li><p>File types</p><ul><li><p>.exe, .com, .obj, .cc, .mov, etc</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled%202.png" /></p></li><li><p>Hint for OS to operate file in a reasonable way</p></li></ul></li></ul><h1 id="access-methods">Access Methods</h1><p>是以使用者的角度來看：</p><ul><li><p>Sequential access</p><ul><li>連續的存取</li><li><code>fread</code>, <code>fwrite</code></li></ul><p><img src="/assets/%5BOS%5DChapter-10/Untitled%203.png" /></p></li><li><p>Direct (relative) access a.k.a random access</p><ul><li>Call API 需要給他位址</li><li>像是使用 table</li><li>使用者要自己維護位址（With great power comes greatresponsibility）</li></ul></li></ul><p><img src="/assets/%5BOS%5DChapter-10/Untitled%204.png" /></p><ul><li>Index Access Methods<ul><li><p>DB</p></li><li><p>用 index 去存取資料</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled%205.png" /></p></li><li><p>Index: contains pointers to blocks of a file</p></li><li><p>With a large file → index could become too large</p></li><li><p>To find a record in a file:</p><ul><li>search the index file → find the pointer</li><li>use the pointer to directly access the record</li></ul></li></ul></li></ul><h2 id="review-slides-i">Review Slides (I)</h2><ul><li>File vs. Sector, Track</li><li>Open-file (in-memory) attributes<ul><li>Per-process, system-wide?</li></ul></li><li>File-access methods?<ul><li>Sequential access</li><li>Direct access</li><li>Index access</li></ul></li></ul><h1 id="directory-structure">Directory Structure</h1><h2 id="directory-basics">Directory Basics</h2><ul><li><p>Partition (Raw partition) — 儲存的空間切割後變成單獨的 partition作是使用和管理，但是這個區塊我們<strong>還沒作格式化的動作</strong></p></li><li><p>Volume — 我們有把他作 formatted（File system 的格式化）的動作了（File system 的專有名詞）→ 強調這是由 <strong>filesystem</strong> 管理使用的空間</p></li><li><p>Directories — used by file system to store the information aboutthe files in the partition</p></li><li><p>File-System Organization</p><figure><img src="/assets/%5BOS%5DChapter-10/Untitled%206.png"alt="Volume 和 Partition 是可以跨 disk 的" /><figcaption aria-hidden="true">Volume 和 Partition 是可以跨 disk的</figcaption></figure></li><li><p>File name 本身也是 directory 的一部分</p><ul><li>因為要找到 file，就要有 file name</li><li>所以 Directory 的最後一層是 file name</li></ul><figure><img src="/assets/%5BOS%5DChapter-10/Untitled%207.png"alt="圈圈是 directory 的最後一層，方框是 file content" /><figcaption aria-hidden="true">圈圈是 directory 的最後一層，方框是 filecontent</figcaption></figure></li><li><p>Directory Operations</p><ul><li>Search for a file</li><li>Create a file</li><li>Delete a file</li><li>List a directory</li><li>Rename a file</li><li>Traverse the file system</li></ul></li></ul><h2 id="directory-structure-1">Directory structure</h2><h3 id="single-level-directory">Single-Level Directory</h3><ul><li>指的是沒有資料夾，完全只有檔案</li><li>Single 指的是 file name</li><li>File name 很容易打架，因為不能重複</li><li>因為是 flat 的，所以每次都要 scan through，效能差</li></ul><p><img src="/assets/%5BOS%5DChapter-10/Untitled%208.png" /></p><h3 id="two-level-directory">Two-Level Directory</h3><ul><li>出現了資料夾</li><li>一個 user 一個資料夾，所以還是有上面的問題</li></ul><p><img src="/assets/%5BOS%5DChapter-10/Untitled%209.png" /></p><h3 id="tree-structured-directory">Tree-Structured Directory</h3><ul><li>Multi-Level</li><li>有 absolute path 和 relative path</li></ul><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2010.png" /></p><h3 id="acyclic-graph-directory">Acyclic-Graph Directory</h3><ul><li>可以建立捷徑到同一個 file</li><li>When does a file actually get deleted?<ol type="1"><li>deleting the link but not the file</li><li>deleting the file but leaves the link → dangling pointer</li></ol>😃 deleting the file when <strong>reference counters</strong> is 0</li></ul><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2011.png" /></p><h3 id="general-graph-directory">General-Graph Directory</h3><ul><li><p>可以隨便亂指，甚至可以有 cycle</p></li><li><p>有可能會明明 access 不到了，但是因為有 link在，所以也沒刪掉檔案</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2012.png" /></p><ul><li><p>Garbage collection</p><p>→ 從 root 開始 traverse，mark 每一個人，沒 mark 到的就刪掉</p><p>☹️ Poor performance</p></li><li><p>Use cycle-detection algorithm when a link is created</p></li></ul></li></ul><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2013.png" /></p><h2 id="review-slides-ii">Review Slides (II)</h2><ul><li>Directory structure: pros &amp; cons<ul><li>One-level directory</li><li>Two-level directory</li><li>Tree-structured directory</li><li>Acyclic-graph directory</li><li>General-graph directory</li></ul></li></ul><h1 id="file-system-mounting-file-sharing">File System Mounting &amp;File Sharing</h1><h2 id="mounting">Mounting</h2><ul><li><p>A file system must be mounted before it can be accessed</p></li><li><p>Mount point — 接到的位址（the root path that a FS will be mountedto），系統槽就是 mount 在 <code>/</code></p></li><li><p>Mount timing: three possibility</p><ol type="1"><li>boot time （系統槽）</li><li>automatically at run-time（USB）</li><li>manually at run-time</li></ol></li><li><p>File System Mounting Example</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2014.png" /></p><ul><li>Partition B 的 mount point 是在 <code>/usr</code></li><li>Partition C 的 mount point 是在 <code>/home</code></li></ul></li><li><p><code>mount –t ext2 /dev/sda0 /mnt/hdd</code></p><ul><li>mount 一個 file type 是 <code>ext2</code> 的（所以知道這是啥FS，才能正確讀取），他現在是 <code>/dev/sda0</code> （是被 I/O deviceattach 成一個檔案的，mount 之後才可以讀取）要 mount 到<code>/mnt/hdd</code></li></ul></li><li><p>How to extend the tree</p><ul><li><p>Tree 長這樣</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2015.png" /></p></li><li><p>前面的 <code>m</code> 代表那不是我管的，是 mount進來的，所以要去查下面的 mount table</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2016.png" /></p></li><li><p>mount 就會修改這裡面的內容</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2017.png" /></p></li></ul></li></ul><h2 id="sharing">Sharing</h2><ul><li><p>基本上都是 multi-user，所以要 sharing，但是要處理permission</p></li><li><p>對於每一個 process，需要去管理他的</p><ul><li>Identity：誰 call 的（Login 就知道了）（也有 groping去幫助管理）</li><li>Permission：知道是誰後要知道他可以動誰</li></ul></li><li><p>Each user — UserID, GroupID</p></li><li><p>Each file has 3 sets of attributes — owner (one and only), group(can operate), others</p><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2018.png" /></p></li><li><p>Access-Control</p><p>Create an access-control list (ACL) for each user</p><ul><li>每次 request 就去查他的權限</li></ul><p>☹️  會太大，每新增一個 user or file ACL will be huger</p><ul><li>3 classes of users → 3 ACL (<strong>RWX</strong>) for each file<ul><li>Owner — (e.g. 7 = RWX = 111)</li><li>group — (e.g. 6 = RWX = 110)</li><li>other (public) — (e.g. 4 = RWX = 100)</li></ul><figure><img src="/assets/%5BOS%5DChapter-10/Untitled%2019.png"alt="chmod 664 intro.ps (第一個 bit 代表他 484 dir)" /><figcaption aria-hidden="true">chmod 664 <ahref="http://intro.ps">intro.ps</a> (第一個 bit 代表他 484dir)</figcaption></figure></li></ul></li></ul><h1 id="protection">Protection</h1><ul><li>Access control protection</li><li>Data failure protection<ul><li>用加密的方式保護他不會遺失</li></ul></li></ul><h2 id="review-slides-iii">Review Slides (III)</h2><ul><li>File system mounting point, timing?</li><li>Access-control list? How does it function?</li></ul><h1 id="textbook-problem-set">Textbook Problem Set</h1><p><img src="/assets/%5BOS%5DChapter-10/Untitled%2020.png" /></p><div class="note warning"><p>此筆記為清華大學周志遠教授作業系統之課堂筆記，所有內容及圖片皆取材於課堂內容。<br />如內容有誤，歡迎來信 <ahref="mailto:mail@arui.dev">mail@arui.dev</a>。</p></div>]]></content>
    
    
    <summary type="html">&lt;div class=&quot;note default&quot;&gt;&lt;p&gt;&lt;a
href=&quot;https://arui-tw.notion.site/Chapter-10-File-System-Interface-588a7531b9aa40058c8423706f01da16&quot;&gt;Notion
好讀版&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;✏️ 從使用者的角度去看&lt;/p&gt;
&lt;/aside&gt;
&lt;h1 id=&quot;file-concept&quot;&gt;File Concept&lt;/h1&gt;
&lt;p&gt;File 也是抽像的概念。&lt;/p&gt;
&lt;aside&gt;
&lt;p&gt;📖 &lt;strong&gt;File (Data)&lt;/strong&gt;: a logical storage unit created by
OS&lt;/p&gt;
&lt;/aside&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Physical storage unit in disk&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/%5BOS%5DChapter-10/Untitled.png&quot; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;File attributes (Metadata)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Identifier: non-human-readable name&lt;/li&gt;
&lt;li&gt;Name&lt;/li&gt;
&lt;li&gt;Type&lt;/li&gt;
&lt;li&gt;Location&lt;/li&gt;
&lt;li&gt;Size&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protection&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Last-access time, Last-updated time&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;File operations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create&lt;/li&gt;
&lt;li&gt;Write&lt;/li&gt;
&lt;li&gt;Read&lt;/li&gt;
&lt;li&gt;Repositioning within a file (i.e. file seek)&lt;/li&gt;
&lt;li&gt;Delete&lt;/li&gt;
&lt;li&gt;Truncating → 切掉尾巴&lt;/li&gt;
&lt;li&gt;Appending → 貼在尾巴</summary>
    
    
    
    <category term="Operating System Notes" scheme="https://blog.arui.dev/categories/Operating-System-Notes/"/>
    
    
    <category term="Operating System" scheme="https://blog.arui.dev/tags/Operating-System/"/>
    
    <category term="Notes" scheme="https://blog.arui.dev/tags/Notes/"/>
    
  </entry>
  
  <entry>
    <title>[OS] Chapter 7 — Deadlocks</title>
    <link href="https://blog.arui.dev/[OS]Chapter-7/"/>
    <id>https://blog.arui.dev/[OS]Chapter-7/</id>
    <published>2022-01-31T10:07:24.000Z</published>
    <updated>2022-02-01T09:09:10.311Z</updated>
    
    <content type="html"><![CDATA[<h1 id="deadlock-characterization">Deadlock Characterization</h1><div class="note default"><p><ahref="https://www.notion.so/arui-tw/Chapter-7-Deadlocks-b345b44b6ac14b28a37bdc7bb497edb9">Notion好讀版</a></p></div><aside><p>📖 程式之間彼此等待，無法進行了</p></aside><ul><li>Example<ul><li>2 processes and 2 tape drivers<ul><li>一人各拿一個，然後等對方手上那個</li></ul></li><li>2 processes, and semaphores A &amp; B<ul><li>P1 (hold B, wait A): wait(A), signal(B)</li><li>P2 (hold A, wait B): wait(B) , signal(A)</li></ul></li></ul></li></ul><p><strong>Necessary Condition</strong> →一定要<strong>全部</strong>的條件<strong>同時</strong>發生</p><ul><li><p>Mutual exclusion — 資源是沒有共享性的（暫時）</p></li><li><p>Hold and Wait — 會 hold resource 然後 wait 別人</p></li><li><p>No preemptive — 不能強制別人放開 resource</p></li><li><p>Circular wait — 一定會有一個 circular 的 wait。</p><p><span class="math inline">\(P_0 \rightarrow P_1 \rightarrow P_1\rightarrow \dots\rightarrow P_n \rightarrow P_0\)</span></p></li></ul><p><img src="/assets/%5BOS%5DChapter-7/Untitled.png" /></p><span id="more"></span><h1 id="system-model">System Model</h1><ul><li><p>要有某些資源 <span class="math inline">\(R_1, R_2, \dots,R_m\)</span></p><ul><li>E.g. CPU, memory pages, I/O devices</li></ul></li><li><p>每個資源 <span class="math inline">\(R_i\)</span>可能會有複數的共 <span class="math inline">\(W_i\)</span> 個instances</p><ul><li>E.g. a computer has 2 CPUs</li></ul></li><li><p>每一個 process 取得 resource 的方式：</p><p>Request → use → release</p></li></ul><h2 id="resource-allocation-graph">Resource-Allocation Graph</h2><figure><img src="/assets/%5BOS%5DChapter-7/Untitled%201.png"alt="圓形跟正方形不能改" /><figcaption aria-hidden="true">圓形跟正方形不能改</figcaption></figure><ul><li>3 processes, P1 <em>~ P3</em></li><li>4 resources, R1 <em>~ R4</em><ul><li>R1 and R3 each has one instance</li><li>R2 has two instances</li><li>R4 has three instances</li></ul></li><li>Request edges:<ul><li>P1 → R1: P1 requests R1 （一直存在因為 resource 正在被用）</li></ul></li><li>Assignment edges:<ul><li>R2 → P1: 那個 instance 正在被 P2 使用</li></ul></li></ul><p>⇒ P1 is hold on an instance of R2 and waiting for an instance ofR1</p><ul><li>If the graph contains a cycle, a deadlock may exist<ul><li><p>如果有 multiple instances，那就要檢查每一條路線都是 cycle才行</p></li><li><p>Example 1</p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%202.png" /></p><ol type="1"><li>P1 is waiting for P2</li><li>P2 is waiting for P3 → P1 is waiting for P3</li><li>P3 is waiting for P1 or P2, and they both waiting for P3</li></ol><p>⇒ deadlock!</p></li><li><p>Example 2</p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%203.png" /></p><ol type="1"><li>P1 is waiting for P2 or P3</li><li>P3 is waiting for P1 or P4</li><li>Since P2 and P4 wait no one</li></ol><p>⇒ no deadlock</p></li></ul></li></ul><h3 id="deadlock-detection">Deadlock Detection</h3><ul><li>沒 cycle → 沒 deadlock</li><li>有 cycle<ul><li>one instance per resource type → 有 deadlock</li><li>multiple instances per resource type → 可能有 deadlock</li></ul></li></ul><h3 id="handling-deadlocks">Handling Deadlocks</h3><ul><li>確保不會進去<ul><li>deadlock prevention — 確保至少一個必要條件不會發生</li><li>deadlock avoidance — 在 runtime 去不斷的檢查</li></ul></li><li>讓他進去再 recover<ul><li>deadlock detection</li><li>deadlock recovery</li></ul></li><li>完全不處理（ignore the problem）<ul><li>讓 user 去中斷他</li></ul></li></ul><h2 id="review-slides-i">Review Slides ( I )</h2><ul><li>deadlock necessary conditions?<ul><li>mutual exclusion</li><li>hold &amp; wait</li><li>no preemption</li><li>circular wait</li></ul></li><li>resource-allocation graph?<ul><li>cycle in RAG → deadlock?</li></ul></li><li>deadlock handling types?<ul><li>deadlock prevention</li><li>deadlock avoidance</li><li>deadlock recovery</li><li>ignore the problem</li></ul></li></ul><h1 id="deadlock-prevention-deadlock-avoidance">Deadlock Prevention&amp; Deadlock Avoidance</h1><h2 id="deadlock-prevention">Deadlock Prevention</h2><ul><li>每一種 resource 各拿掉一種條件。（每一個可以不一樣）<ul><li><p>Mutual exclusion (ME): do not require ME on sharableresources</p><ul><li>E.g. set file to read only → no mutual exclusion (can many read insame time)</li><li>但不是所有都可以這樣解</li><li>（Memory 是 support concurrent access 的，是 programer 的行為讓他有ME 的條件出來的）</li></ul></li><li><p>Hold &amp; Wait</p><ul><li>規定他要 free 掉手上的 resource 才能去要其他resource。或是一就要把全部的 resource 要齊（只要要等就要把拿到的 free掉，可以等，但是手上不能有東西）。</li><li>All or nothing allocation</li><li>去改變 mutex_wait 的實作</li></ul><p>☹️ Resource 使用率降低，可能會有 starvation</p></li><li><p>No preemption</p><ul><li>改成可以作 preemptive</li><li>E.g. preemptive 的 scheduler → 有 timer 去讓 OS always controlCPU</li></ul><p>☹️ Overhead，要多一塊 memory 去暫存資料</p><p>→ Printer 的代價就太高了（要重印）</p></li><li><p>Circular wait</p><ul><li><p>在 request resource 的時候，如果你要 request <spanclass="math inline">\(R_k\)</span>，那就要 release <spanclass="math inline">\(R_i, \forall i \geq k\)</span>。（小於 <spanclass="math inline">\(k\)</span> 的可以繼續 hold）</p><p>手上不能握比較大的。</p></li><li><p>Example</p><ul><li>F(<em>tape drive</em>) = 1, F(<em>disk drive</em>) = 5,F(<em>printer</em>) = 12</li><li>如果 hold disk，可以要 printer</li><li>如果 hold printer 和 tape，那 request drive 就要 releaseprinter，tape 可以留著</li></ul></li><li><p>Proof</p><ul><li><p>證明有 deadlock 但是不可能成立</p></li><li><p><span class="math inline">\(P_0(R_0) \rightarrowR_1\)</span>(<span class="math inline">\(P_0\)</span> hold <spanclass="math inline">\(R_0\)</span> and request <spanclass="math inline">\(R_1\)</span>)</p><p><span class="math inline">\(P_1(R_1) \rightarrow R_2, \dots, P_N(R_N)\rightarrow \red {R_0}\)</span></p></li><li><p>但是最後一個不可能成立，因為 <spanclass="math inline">\(N&gt;0\)</span></p></li></ul></li></ul></li></ul></li></ul><h2 id="avoidance-algorithms">Avoidance Algorithms</h2><ul><li><p>Single instance of a resource type</p><p>→ 用 resource-allocation graph (RAG) algorithm ****直接偵測circle</p></li><li><p>Multiple instances of a resource type</p><p>→ banker’s algorithm</p></li></ul><h3 id="resource-allocation-graph-rag-algorithm">Resource-AllocationGraph (RAG) Algorithm</h3><p><img src="/assets/%5BOS%5DChapter-7/Untitled%204.png" /></p><ul><li>Request edges:<ul><li><span class="math inline">\(P_i \rightarrow R_j\)</span>: <spanclass="math inline">\(P_i\)</span> waiting for <spanclass="math inline">\(R_j\)</span></li></ul></li><li>Assignment edges:<ul><li><span class="math inline">\(R_j → P_i\)</span>: <spanclass="math inline">\(R_j\)</span> is allocated and held by <spanclass="math inline">\(P_i\)</span></li><li>Resource 被 release 可能轉回 claim edge</li></ul></li><li>Claim edge:<ul><li><span class="math inline">\(P_i \rightarrow R_j\)</span>: <spanclass="math inline">\(P_i\)</span> may request <spanclass="math inline">\(R_j\)</span> <strong>in the future</strong> (worstcase)</li><li>真的發生就會變成 request edges</li></ul></li><li>Example<ul><li><p>這不會出事</p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%205.png" /></p></li><li><p>當 P2 request for R1 的時候，他會被擋掉。因為我們會假設 claim的情形會在未來 somehow 發生。</p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%206.png" /></p></li></ul></li><li>Cycle-detection algorithm ⇒ <spanclass="math inline">\(O(n^2)\)</span></li></ul><h3 id="bankers-algorithm"><strong>Banker’s algorithm</strong></h3><p>去考慮 worse case。</p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%207.png" /></p><ul><li>Safe state → 可以找到一個 safe sequence讓程式照著跑，結束前都不會遇到 deadlock</li><li>Unsafe state → 有機率會 deadlock</li><li>Deadlock avoidance → 不要進到 unsafe</li></ul><p><strong>Safe Sequence</strong></p><ul><li><p>Assume 有 12 個 tape drives</p></li><li><p>Safe state:</p><ul><li><p>At t0:</p><table><thead><tr class="header"><th></th><th>Max Needs</th><th>Current Holding</th></tr></thead><tbody><tr class="odd"><td>P0</td><td>10</td><td>5</td></tr><tr class="even"><td>P1</td><td>4</td><td>2</td></tr><tr class="odd"><td>P2</td><td>9</td><td>2</td></tr></tbody></table><ul><li>Max need is hinted from processes</li><li>Max need is worst case</li></ul><p>→ &lt;P1, P0, P2&gt; is a safe sequence</p><ol type="1"><li><p>給 P1 3 個（有的都給他）</p><table><thead><tr class="header"><th></th><th>Max Needs</th><th>Current Holding</th><th>Available</th></tr></thead><tbody><tr class="odd"><td>P0</td><td>10</td><td>5</td><td></td></tr><tr class="even"><td>P1</td><td>4</td><td>2</td><td>3</td></tr><tr class="odd"><td>P2</td><td>9</td><td>2</td><td></td></tr></tbody></table></li><li><p>給 P0 5 個</p><table><thead><tr class="header"><th></th><th>Max Needs</th><th>Current Holding</th><th>Available</th></tr></thead><tbody><tr class="odd"><td>P0</td><td>10</td><td>5</td><td>5</td></tr><tr class="even"><td>P1</td><td>4</td><td>0</td><td>0</td></tr><tr class="odd"><td>P2</td><td>9</td><td>2</td><td></td></tr></tbody></table></li><li><p>給 P2 10 個</p><table><thead><tr class="header"><th></th><th>Max Needs</th><th>Current Holding</th><th>Available</th></tr></thead><tbody><tr class="odd"><td>P0</td><td>10</td><td>0</td><td></td></tr><tr class="even"><td>P1</td><td>4</td><td>0</td><td></td></tr><tr class="odd"><td>P2</td><td>9</td><td>2</td><td>10</td></tr></tbody></table></li></ol></li></ul></li><li><p>Unsafe state:</p><ul><li><p>At t1:</p><p>假設這時候 OS 拿到的一個 request 說 P2 想要多一個 tape drive。</p><table><thead><tr class="header"><th></th><th>Max Needs</th><th>Current Holding</th><th>Available</th></tr></thead><tbody><tr class="odd"><td>P0</td><td>10</td><td>5</td><td></td></tr><tr class="even"><td>P1</td><td>4</td><td>2</td><td>3 → 2</td></tr><tr class="odd"><td>P2</td><td>9</td><td>2 → 3</td><td></td></tr></tbody></table><ul><li>跑一次上面的流程，然後我們就會發現，如果我們同意了（P2 的 currentholding 變成 3 了），我們就會發現他可能會 deadlock （i.e. 進到 unsafestate）。</li><li>所以 OS 就會擋掉這個 request。</li></ul></li></ul></li><li><p>Banker algorithm:</p><ol type="1"><li><p>拿到 request，先假設同意了</p></li><li><p>然後去跑 safe sequence</p><p>選 sequence 的順序隨便都沒差。</p></li><li><p>如果 safe sequence 存在，我們就 grant request，反之就不同意</p><p>如果有數個，那就都可以，反正至少一個就好了</p></li></ol></li><li><p>Banker’s Algorithm Example 1</p><p>我懶得貼.. P.27</p></li><li><p>Programming Example</p><p>A, B, C are semaphores initialized with the values of 2, 1, 1.</p><p>用 round-robin 跑。</p><ul><li><p>原本</p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%208.png" /></p></li><li><p>Use avoidance</p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%209.png" /></p><ul><li>P4 的 wait(A) 如果成功了，加上 claim edge 就會 dead lock，所以 OS不會讓他拿</li><li>接下來 P2 就會搶到 A，然後 eventually 他就會 signal A andC，剩下的就會成功結束了</li></ul></li></ul></li></ul><h2 id="review-slides-ii">Review Slides (II)</h2><ul><li>deadlock prevention methods?<ul><li>mutual exclusion</li><li>hold &amp; wait</li><li>no preemption</li><li>circular wait</li></ul></li><li>deadlock avoidance methods?<ul><li>safe state definition?</li><li>safe sequence?</li><li>claim edge?</li></ul></li></ul><h1 id="deadlock-detection-recovery-from-deadlock">Deadlock Detection&amp; Recovery from Deadlock</h1><ul><li><p>deadlock 了再解</p><p>（就算卡住了，也只是 user program，OS 一定不會卡住的啦，要信任OS）</p></li><li><p>所以就就當下的情況去跑上面那些 check</p></li><li><p>Single instance</p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%2010.png" /></p></li><li><p>Multiple-Instance → Banker’s algorithm</p><ul><li>可以把 Max Needs 拿掉，沒用了</li><li>去檢查有沒有 safe sequence 存在，有就當作沒事。沒有就代表進入deadlock 了。</li></ul><p><img src="/assets/%5BOS%5DChapter-7/Untitled%2011.png" /></p></li><li><p>Deadlock Recovery</p><p>→ Process termination</p><ul><li>但是要 kill 誰？（可能可以 kill priority 低的）（但是一直 killpriority 低的可能會 starvation ）</li><li>Kill 掉之後還可以 roll back 嗎？</li></ul></li></ul><h1 id="textbook-problem-set">Textbook Problem Set</h1><p><img src="/assets/%5BOS%5DChapter-7/Untitled%2012.png" /></p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%2013.png" /></p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%2014.png" /></p><p><img src="/assets/%5BOS%5DChapter-7/Untitled%2015.png" /></p><div class="note warning"><p>此筆記為清華大學周志遠教授作業系統之課堂筆記，所有內容及圖片皆取材於課堂內容。<br />如內容有誤，歡迎來信 <ahref="mailto:mail@arui.dev">mail@arui.dev</a>。</p></div>]]></content>
    
    
    <summary type="html">&lt;h1 id=&quot;deadlock-characterization&quot;&gt;Deadlock Characterization&lt;/h1&gt;
&lt;div class=&quot;note default&quot;&gt;&lt;p&gt;&lt;a
href=&quot;https://www.notion.so/arui-tw/Chapter-7-Deadlocks-b345b44b6ac14b28a37bdc7bb497edb9&quot;&gt;Notion
好讀版&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;aside&gt;
&lt;p&gt;📖 程式之間彼此等待，無法進行了&lt;/p&gt;
&lt;/aside&gt;
&lt;ul&gt;
&lt;li&gt;Example
&lt;ul&gt;
&lt;li&gt;2 processes and 2 tape drivers
&lt;ul&gt;
&lt;li&gt;一人各拿一個，然後等對方手上那個&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;2 processes, and semaphores A &amp;amp; B
&lt;ul&gt;
&lt;li&gt;P1 (hold B, wait A): wait(A), signal(B)&lt;/li&gt;
&lt;li&gt;P2 (hold A, wait B): wait(B) , signal(A)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Necessary Condition&lt;/strong&gt; →
一定要&lt;strong&gt;全部&lt;/strong&gt;的條件&lt;strong&gt;同時&lt;/strong&gt;發生&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Mutual exclusion — 資源是沒有共享性的（暫時）&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hold and Wait — 會 hold resource 然後 wait 別人&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No preemptive — 不能強制別人放開 resource&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Circular wait — 一定會有一個 circular 的 wait。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;math inline&quot;&gt;&#92;(P_0 &#92;rightarrow P_1 &#92;rightarrow P_1
&#92;rightarrow &#92;dots&#92;rightarrow P_n &#92;rightarrow P_0&#92;)&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/assets/%5BOS%5DChapter-7/Untitled.png&quot; /&gt;&lt;/p&gt;</summary>
    
    
    
    <category term="Operating System Notes" scheme="https://blog.arui.dev/categories/Operating-System-Notes/"/>
    
    
    <category term="Operating System" scheme="https://blog.arui.dev/tags/Operating-System/"/>
    
    <category term="Notes" scheme="https://blog.arui.dev/tags/Notes/"/>
    
  </entry>
  
  <entry>
    <title>[OS] Chapter 6 — Process Synchronization</title>
    <link href="https://blog.arui.dev/[OS]Chapter-6/"/>
    <id>https://blog.arui.dev/[OS]Chapter-6/</id>
    <published>2022-01-31T10:06:24.000Z</published>
    <updated>2022-02-01T14:18:25.755Z</updated>
    
    <content type="html"><![CDATA[<div class="note default"><p><ahref="https://arui-tw.notion.site/Chapter-6-Process-Synchronization-dc2fdd2951b047f78a39377759ebe90c">Notion好讀版</a></p></div><h1 id="background">Background</h1><ul><li>因為有 share 的 data，會被多個 content 去用他，所以需要</li><li>就算只有一個 core，也會有 Concurrent 的問題（因為會有 contentswitch）</li><li>重點就是他們 execute 的 order</li><li>Consumer &amp; Producer Problem<ul><li><p>用 counter 去記還有幾個空位</p></li><li><p>Producer</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) &#123;</span><br><span class="line">nextItem = <span class="built_in">getItem</span>( );</span><br><span class="line"><span class="keyword">while</span> (counter == BUFFER_SIZE);</span><br><span class="line">buffer[in] = nextItem;</span><br><span class="line">in = (in + <span class="number">1</span>) % BUFFER_SIZE;</span><br><span class="line">counter++;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p></li><li><p>Consumer</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">while</span> (counter == <span class="number">0</span>) ;</span><br><span class="line">item = buffer[out];</span><br><span class="line">out = (out + <span class="number">1</span>) % BUFFER_SIZE;</span><br><span class="line">counter--;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p></li><li><p>但是 counter 會是這兩隻 thread共用的東東，所以會出現不一致的問題：</p><ul><li><p><code>counter++</code></p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">move ax, counter</span><br><span class="line">add  ax, <span class="number">1</span></span><br><span class="line">move counter, ax</span><br></pre></td></tr></table></figure></p></li><li><p><code>counter--</code></p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">move bx, counter</span><br><span class="line">sub  bx, <span class="number">1</span></span><br><span class="line">move counter, bx</span><br></pre></td></tr></table></figure></p></li><li><p>但是…如果是這樣呢？（counter initially is 5）</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">producer: move ax, counter   <span class="comment">// ax = 5</span></span><br><span class="line">producer: add ax, <span class="number">1</span>          <span class="comment">// ax = 6</span></span><br><span class="line">context <span class="keyword">switch</span></span><br><span class="line">consumer: move bx, counter   <span class="comment">// bx = 5</span></span><br><span class="line">consumer: sub bx, <span class="number">1</span>          <span class="comment">// bx = 4</span></span><br><span class="line">context <span class="keyword">switch</span></span><br><span class="line">producer: move counter, ax   <span class="comment">// counter = 6</span></span><br><span class="line">context <span class="keyword">switch</span></span><br><span class="line">consumer: move counter, bx   <span class="comment">// counter = 4</span></span><br></pre></td></tr></table></figure></p><p>不過如果不是 preemptive 就不會有這個問題了。</p></li></ul></li></ul></li></ul><h2 id="race-condition">Race Condition</h2><aside><p>📖 多個 process 操作 shared dataconcurrently，結果會取決於最後完成的人。（這是描述一個問題點，所以是因為有race condition，要用同步化解決）</p></aside><ul><li>Single processor 的可以用 disable interrupt 或 non-preemptive CPU來解決。</li></ul><span id="more"></span><h1 id="critical-section">Critical Section</h1><ul><li><p><del>一個 process 之間溝通的 protocol</del></p></li><li><p>Critical section: 會產生 race condition 的那段程式碼。</p></li><li><p>Mutually exclusive: 會有相同 critical section 的process。他們要在那段 critical section 被迫去 serialize。</p><figure><img src="/assets/%5BOS%5DChapter-6/Untitled.png"alt="Remainder section: 剩下的" /><figcaption aria-hidden="true">Remainder section: 剩下的</figcaption></figure></li></ul><h2 id="critical-section-requirements">Critical SectionRequirements</h2><ol type="1"><li>Mutual Exclusion: if process P is executing in its CS, no otherprocesses can be executing in their CS</li><li>Progress: 有 process 想要進去空的 criticalsection，就應該要讓他馬上進去。（有效性）</li><li>Bounded Waiting: 不能讓等的人一直等，要 bound 他的 waitingtime。（公平性）</li></ol><ul><li>2 和 3 是可捨取的</li></ul><h2 id="review-slide">Review Slide</h2><ul><li>Race condition?</li><li>Critical-Section (CS) problem? 4 sections?<ul><li>entry, CS, exit, remainder</li></ul></li><li>3 requirements for solutions to CS problems?<ul><li>mutual exclusion</li><li>progress</li><li>bounded waiting</li></ul></li></ul><h1 id="software-solution">Software Solution</h1><ul><li><p>Assume only 2 processes, <span class="math inline">\(P_0\)</span>and <span class="math inline">\(P_1\)</span></p></li><li><p>用 <code>turn</code> 決定輪到誰</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%201.png" /></p><ul><li>因為是用 single instruction 去 set，所以不會被中斷詠唱</li><li>Requirements<ol type="1"><li>Mutual Exclusion: Yes</li><li>Progress: <strong>Nope</strong>，不符合 Progress 的條件， 因為 <spanclass="math inline">\(P_0\)</span> 可能已經繞一圈想上去了，但是因為<span class="math inline">\(P_1\)</span> 還沒進過 CS，所以他進不去</li><li>Bounded Waiting: Yes，因為是 Round robin.</li></ol></li></ul></li></ul><h2 id="petersons-solution-for-two-processes">Peterson’s Solution forTwo Processes</h2><ul><li><p>跟剛剛那個很像，但是多了一個 flag，用來表示他是不是想要進去critical section（True 就是他準備好進去了）</p></li><li><p>對方可以看到別人的 flag，但是只有自己可以改自己的</p></li><li><p>所以進去的時候就是別人不想進去，或是你拿到 token 了（i.e.對方沒拿到 token）</p><figure><img src="/assets/%5BOS%5DChapter-6/Untitled%202.png"alt="注意是要在進去前把 turn 值給對方" /><figcaption aria-hidden="true">注意是要在<strong>進去前</strong>把 turn值給對方</figcaption></figure></li></ul><h3 id="proof">Proof</h3><ul><li>Mutual exclusion: 用反證<ol type="1"><li><p>假設他們可以同時在裡面</p></li><li><p>那下面的條件就要同時存在。</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%203.png" /></p></li><li><p>因為他們都在裡面，所以 flag 都是 true</p></li><li><p>但是 turn 不可能同時是 0 且 1</p></li><li><p>所以不可能同時進去</p></li></ol></li><li>Progress<ol type="1"><li>假設 <span class="math inline">\(P_0\)</span> 想要進去，且 <spanclass="math inline">\(P_1\)</span> 不想要進去，要證這時候 <spanclass="math inline">\(P_0\)</span> 應該要要可以進去 ⇒好像也不用證，反正就可以啊</li><li>兩個都想進去的時候，那就看<code>turn</code>，一定有其中一個可以進去</li></ol></li><li>Bounded Waiting<ul><li>假設當 <span class="math inline">\(P_1\)</span> 想要進去，但是 <spanclass="math inline">\(P_0\)</span> 在裡面。</li></ul><ol type="1"><li><p><span class="math inline">\(P_0\)</span> 一離開 CS 就把<code>flag</code> 設成 False 了，所以馬上就輪到 <spanclass="math inline">\(P_1\)</span> 了</p></li><li><p><span class="math inline">\(P_0\)</span> 如果一離開 CS就又想進去（可能因為剩下的都是 CPU burst，所以就沒有被 content switch掉）</p><p>⇒ 但是因為會在最一開始把 token 給別人，所以會被讓給別人作</p></li></ol></li></ul><h2 id="producerconsumer-problem">Producer/Consumer Problem</h2><ul><li><p>如果先進 Consumer 就會 deadlock（i.e. 程式沒有在前進，但是 CPU在燒）。</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%204.png" /></p></li><li><p>正確但是低效能。</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%205.png" /></p></li><li><p>正確且優質。</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%206.png" /></p></li></ul><h2 id="bakery-algorithm-n-processes">Bakery Algorithm (nprocesses)</h2><ul><li>像去麵包店</li></ul><ol type="1"><li>在每次進去 CS 前，要抽號碼牌</li><li>號碼牌最小的先進（因為 counter 是用 <code>++</code>的，所以<strong>只能</strong>保證是 non-decrease order 的，e.g. 1, 2, 3,3, 4, 4, 4, 5）</li><li>如果號碼牌一樣，就根據 process ID，小的先</li></ol><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Process i</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">choosing[i] = <span class="literal">true</span>;  <span class="comment">// 開始抽</span></span><br><span class="line">num[i] = <span class="built_in">max</span>(num[<span class="number">0</span>], num[<span class="number">1</span>], ..., num[n<span class="number">-1</span>]) + <span class="number">1</span>; <span class="comment">// get ticket</span></span><br><span class="line">choosing[i] = <span class="literal">false</span>; <span class="comment">// 抽完了</span></span><br><span class="line"><span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; n; j++) &#123;</span><br><span class="line"><span class="keyword">while</span> (choosing[j]);  <span class="comment">// 確定他抽完了才可以比</span></span><br><span class="line"><span class="keyword">while</span> ((num[j] != <span class="number">0</span>) &amp;&amp;     <span class="comment">// num 是 0 就是不想進去</span></span><br><span class="line"> ((num[j], j) &lt; (num[i], i))); <span class="comment">// 比較每一個 j 確定我是最小的</span></span><br><span class="line">&#125;</span><br><span class="line">**critical section**</span><br><span class="line">num[i] = <span class="number">0</span>;</span><br><span class="line">**reminder section**</span><br><span class="line">&#125; <span class="keyword">while</span>(<span class="number">1</span>);</span><br></pre></td></tr></table></figure><ul><li>最小號碼一定先做 → first come first serve → bounded-waitingtime</li><li>如果沒有 choosing<ol type="1"><li>假設目前最大是 5</li><li>P4 抽的比較快，抽到 6，這時候 P1 還是 0</li><li>然後 P4 會進去 CS（他這時候會以為 P1 沒有要進去，因為他是 0）</li><li>接下來 P1 抽完了，抽到 6，他就去跟 P4 比，發現跟他一樣，但是他的 pid比較小，所以他就開開心心的進去了。然後就沒有然後了。(race conditionby355)</li></ol><ul><li>如果有 locking，P4 就會等到 P1 先抽完再跟他比</li></ul></li></ul><h1 id="synchronization-hardware">Synchronization Hardware</h1><p>只要用到 Hardware 的就算是（包括之前的 disable interrupt）</p><h2 id="atomic-instruction">Atomic instruction</h2><p>一個 CPU 的 instruction，所以一定會一次做完。</p><p>不需要 library 的 support，內建就有了。</p><h3 id="testandset"><code>TestAndSet()</code></h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">boolean <span class="title">TestAndSet</span> <span class="params">(<span class="type">bool</span> &amp;lock)</span> </span>&#123;</span><br><span class="line"><span class="type">bool</span> value = lock;</span><br><span class="line">lock = TRUE;   <span class="comment">// 不論結果，都會鎖起來</span></span><br><span class="line"><span class="keyword">return</span> value;  <span class="comment">// return 的是原本的值</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="/assets/%5BOS%5DChapter-6/Untitled%207.png" /></p><ul><li><p>Mutual exclusion: Yes</p><p>⇒ 因為只有正在 CS 裡面的人把他設成 False 才可以放下一個進去</p></li><li><p>Progress: Yes</p><p>⇒ 只要沒人在裡面，想進去就可以馬上進去</p></li><li><p>Bounded-Wait: No</p><p>⇒ 因為先搶先贏，所以可能一直搶不到</p><p>⇒ P0 的 CS 結束了，但是 CPU burst 還沒完，所以他又搶到lock，然後進去之後 CPU burst 結束了，content switch。換P1，但是他被擋在外面，CPU burst 燒完之後都輪不到他 QQ，又回到 P0繼續。</p></li></ul><h3 id="swap"><code>Swap()</code></h3><p>把值對調。</p><figure><img src="/assets/%5BOS%5DChapter-6/Untitled%208.png"alt="一開始會把 key 設成 True，然後就在 while 裡面一直把 lock 跟 key 交換。如果 lock 在別的地方被設成 False 了，就可以進去 CS 了。" /><figcaption aria-hidden="true">一開始會把 key 設成 True，然後就在 while裡面一直把 lock 跟 key 交換。如果 lock 在別的地方被設成 False了，就可以進去 CS 了。</figcaption></figure><ul><li>特性也跟剛剛一樣</li></ul><h2 id="review-slide-2">Review Slide (2)</h2><ul><li>Use software solution to solve CS?<ul><li>Peterson’s and Bakery algorithms</li></ul></li><li>Use HW support to solve CS?<ul><li><code>TestAndSet()</code>, <code>Swap()</code></li></ul></li></ul><h1 id="semaphores">Semaphores</h1><ul><li>Resource counting 的問題。</li><li>一個值 indicate 想要透過 semaphore 保護的資源的數量多寡。<ul><li>If #record = 1 → binary semaphore, mutex lock</li><li>if #record &gt; 1 → counting semaphore</li></ul></li><li>用兩個 atomic operation：<ol type="1"><li><p><code>wait</code>：搶資源</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">wait</span>(S) &#123;</span><br><span class="line"><span class="keyword">while</span> (S &lt;= <span class="number">0</span>); <span class="comment">// busy waiting</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>用的是 Spinlock → 等待還是會燒 CPU（因為一直在作指令）</p></li><li><p><code>signal</code>：放資源</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">signal</span>(S) &#123;</span><br><span class="line">S++;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p></li></ol></li></ul><h2 id="posix-semaphore">POSIX Semaphore</h2><ul><li><p>他是 OS 的 API</p></li><li><p>Semaphore is part of POSIX standard BUT it is not belonged toPthread</p><ul><li>It can be used with or <strong>without</strong> thread</li></ul></li><li><p>因為 lock 多是在 threads 之間，semaphore 多是在 process之間。</p></li><li><p>POSIX Semaphore routines:</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sem_init</span>(<span class="type">sem_t</span> *sem, <span class="type">int</span> pshared, <span class="type">unsigned</span> <span class="type">int</span> value)</span><br><span class="line"><span class="built_in">sem_wait</span>(<span class="type">sem_t</span> *sem)</span><br><span class="line"><span class="built_in">sem_post</span>(<span class="type">sem_t</span> *sem)</span><br><span class="line"><span class="built_in">sem_getvalue</span>(<span class="type">sem_t</span> *sem, <span class="type">int</span> *valptr) <span class="comment">// check</span></span><br><span class="line"><span class="built_in">sem_destroy</span>(<span class="type">sem_t</span> *sem)</span><br></pre></td></tr></table></figure></p></li><li><p>Example:</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;semaphore.h&gt;</span></span></span><br><span class="line"><span class="type">sem_t</span> sem;</span><br><span class="line"><span class="built_in">sem_init</span>(&amp;sem);</span><br><span class="line"><span class="built_in">sem_wait</span>(&amp;sem);</span><br><span class="line"><span class="comment">// critical section</span></span><br><span class="line"><span class="built_in">sem_post</span>(&amp;sem);</span><br><span class="line"><span class="built_in">sem_destroy</span>(&amp;sem);</span><br></pre></td></tr></table></figure></p></li><li><p>Another example</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line"><span class="built_in">wait</span>(mutex);   <span class="comment">// pthread_mutex_lock(&amp;mutex)</span></span><br><span class="line"><span class="comment">// critical section</span></span><br><span class="line"><span class="built_in">signal</span>(mutex); <span class="comment">// pthread_mutex_unlock(&amp;mutex)</span></span><br><span class="line"><span class="comment">// remainder section</span></span><br><span class="line">&#125; <span class="keyword">while</span>(<span class="number">1</span>);</span><br></pre></td></tr></table></figure></p><ul><li>Progress: Yes</li><li>Bounded waiting: 取決於 <code>wait</code> 的實作</li></ul></li></ul><h2 id="non-busy-waiting-implementation">Non-busy waitingImplementation</h2><aside><p>✏️ Waiting 的應該要被 put to sleep（所以有要要去 wake up 他）</p></aside><ul><li><p>Semaphore is data struct with a queue （可以用各種 queuestrategy）</p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span> &#123;</span><br><span class="line"><span class="type">int</span> value;        <span class="comment">// init to 0</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">process</span> *L;</span><br><span class="line"><span class="comment">// “PCB” queue </span></span><br><span class="line">&#125; semaphore;</span><br></pre></td></tr></table></figure></p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%209.png" /></p></li><li><p><code>wait()</code> and <code>signal()</code></p><ul><li>需要用到 <code>block()</code> and <code>wakeup()</code> 兩個 systemcalls。（明顯的缺點，需要多用到 system call）</li></ul><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">signal</span><span class="params">(semaphore S)</span> </span>&#123; </span><br><span class="line">S.value++;</span><br><span class="line"><span class="keyword">if</span> (S.value &lt;= <span class="number">0</span>) &#123;         <span class="comment">// 注意有 `=`，因為我們先 `++` 了 </span></span><br><span class="line">remove a process P from S.L; </span><br><span class="line"><span class="built_in">wakeup</span>(P);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">wait</span><span class="params">(semaphore S)</span> </span>&#123;</span><br><span class="line">S.value--;  <span class="comment">// subtract first</span></span><br><span class="line"><span class="keyword">if</span> (S.value &lt; <span class="number">0</span>) &#123;         <span class="comment">// 注意沒有 `=`</span></span><br><span class="line">add <span class="keyword">this</span> process to S.L; <span class="comment">// 要先放進去才能去睡覺</span></span><br><span class="line"><span class="built_in">block</span>();</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p></li><li><p>更多行加上更多 share data（那些 queue），所以要確保他有 atomic的特性。可以用：</p><ul><li>Single-processor: disable interrupts</li><li>Multi-processor:<ul><li>HW support (e.g. Test-And-Set, Swap)</li><li>SW solution (Peterson’s solution, Bakery algorithm)</li></ul></li></ul><figure><img src="/assets/%5BOS%5DChapter-6/Untitled%2010.png"alt="注意不要包到 sleep 和 wakeup，不然會 deadlock。" /><figcaption aria-hidden="true">注意不要包到 sleep 和 wakeup，不然會deadlock。</figcaption></figure></li><li><p>如果等待時間短，不如用 busy waiting，不然要一直 call systemcall。</p></li></ul><h2 id="cooperation-synchronization">Cooperation Synchronization</h2><p>因為會有資料的 independency，所以也可以用這個來解。</p><ul><li><p>Example:</p><ul><li><p>P1 executes S1; P2 executes S2 (S2 be executed only after S1 hascompleted)</p></li><li><p><code>sync</code> 一開始設成 0</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2011.png" /></p></li></ul></li><li><p>A More Complicated Example (DAG)</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2012.png" /></p><ul><li>(Initially, all semaphores are 0)</li></ul><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2013.png" /></p></li></ul><h2 id="deadlocks-starvation">Deadlocks &amp; Starvation</h2><ul><li>Deadlocks: 2 processes are waiting indefinitely for each other torelease resources（程式之間彼此互卡）</li><li>Starvation:<ul><li>example: LIFO (Last In First Out) queue in semaphore processqueue</li><li>有人可以執行只是輪不到我</li></ul></li></ul><h2 id="review-slide-3">Review Slide (3)</h2><ul><li>What’s semaphore? 2 operations?</li><li>What’s busy-waiting (Spinlock) semaphore?</li><li>What’s non-busy-waiting (Non-Spinlock) semaphore?</li><li>How to ensure atomic wait &amp; signal ops?</li><li>Deadlock? starvation?</li></ul><h1 id="classical-problems-of-synchronization">Classical Problems ofSynchronization</h1><p>解決方法很多，重點是去定義問題。</p><ul><li>Bounded-Buffer (Producer-Consumer) Problem</li><li>Reader-Writers Problem</li><li>Dining-Philosopher Problem</li></ul><h2 id="bounded-buffer-problem">Bounded-Buffer Problem</h2><p>就上面那些問題。</p><ul><li>A pool of <em>n</em> buffers, each capable of holding one item</li><li>Producer:<ul><li>grab an empty buffer</li><li>place an item into the buffer</li><li>waits if no empty buffer is available</li></ul></li><li>Consumer:<ul><li>grab a buffer and retracts the item</li><li>place the buffer back to the free pool</li><li>waits if all buffers are empty</li></ul></li></ul><h2 id="readers-writers-problem">Readers-Writers Problem</h2><ul><li>reader processes → 只會讀</li><li>writer processes → 只會寫</li><li>如果都是 reader 那沒差，反正同時 read 也不會出事。但是 writer就只能一個人寫，連 reader 都不能同時 read。（Exclusive access）</li><li>Different variations involving priority<ul><li><p><strong>First RW problem</strong>: no reader will be kept waitingunless a writer is updating a shared object（只要符合上面的基本定義就好了）</p></li><li><p><strong>Second RW problem</strong>: first 的條件加上 writer 不能starvation。</p><p>→ Writer 要比較高的 priority</p><p>→ once a writer is ready, no new reader may start reading</p></li></ul></li></ul><h3 id="first-reader-writer-algorithm">First Reader-WriterAlgorithm</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// mutual exclusion for write</span></span><br><span class="line">semaphore wrt = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// mutual exclusion for readcount</span></span><br><span class="line">semaphore mutex=<span class="number">1</span>  <span class="comment">// 保護 readcount</span></span><br><span class="line"><span class="type">int</span> readcount=<span class="number">0</span>;   <span class="comment">// 有多少人要 read</span></span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Writer</span>() &#123; </span><br><span class="line"><span class="keyword">while</span>(<span class="literal">true</span>) &#123;</span><br><span class="line"><span class="built_in">wait</span>(wrt);</span><br><span class="line">**<span class="comment">// Writer Code**</span></span><br><span class="line"><span class="built_in">signal</span>(wrt);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Reader</span>() &#123;</span><br><span class="line"><span class="keyword">while</span>(<span class="literal">true</span>) &#123;</span><br><span class="line"><span class="built_in">wait</span>(mutex);</span><br><span class="line"></span><br><span class="line">readcount++;</span><br><span class="line"><span class="comment">// Acquire write lock if reads haven’t</span></span><br><span class="line"><span class="comment">// 全部 reader 共用一個 write lock</span></span><br><span class="line"><span class="keyword">if</span> (readcount == <span class="number">1</span>) <span class="comment">// 代表原本沒有人在 read</span></span><br><span class="line"><span class="built_in">wait</span>(wrt);        <span class="comment">// 所以需要要過來</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">signal</span>(mutex);</span><br><span class="line"></span><br><span class="line">**<span class="comment">// Reader Code**</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">wait</span>(mutex);</span><br><span class="line"></span><br><span class="line">readcount--;</span><br><span class="line"><span class="comment">// release write lock if no more reads</span></span><br><span class="line"><span class="keyword">if</span> (readcount == <span class="number">0</span>)  <span class="comment">// 代表沒有人要 read 了</span></span><br><span class="line"><span class="built_in">signal</span>(wrt);       <span class="comment">// 就可以放掉了</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">signal</span>(mutex);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><p>Writer 會有 starvation，因為 reader 共用一個lock，所以可以一直輪流佔著</p><p>⇒ Second RW problem solve it.</p></li></ul><h3 id="dining-philosophers-problem">Dining-Philosophers Problem</h3><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2014.png" /></p><ul><li>每個人左邊跟右邊都有一根筷子（五個人五隻筷子）<ul><li>吃飯需要兩隻筷子</li><li>一隻筷子只能一個人拿</li><li>吃完就要把筷子放下</li></ul></li><li>Deadlock problem<ul><li>每個人拿左邊的筷子直到吃完飯 → 卡死</li></ul></li><li>Starvation problem<ul><li>不能讓人一直拿，一直吃</li></ul></li></ul><h1 id="monitors">Monitors</h1><aside><p>💡 動機：因為前面很難，要在對的地方用對的東西，不能多，不能少。</p></aside><ul><li><p>目的是要更抽象化（他是在 language level）</p></li><li><p>跟 OO 很像</p></li><li><p>像是由一個 class 定義的東西：有自己的 methods、variables、privatevariables。</p></li><li><p>（Private variables 只能由自己的 methods 操作）</p></li><li><p>和 OO 不同的是他會確保他的 process 只會有一個在<strong>active</strong> (running) 的狀態</p></li><li><p>Schematic View ****</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2015.png" /></p><ul><li>Shared data → private variable</li><li>Operations → methods</li><li>Initialization code → constructor</li><li>Entry queue → 想要用 monitors 的傢伙</li></ul></li></ul><h2 id="monitor-condition-variables">(Monitor) Condition Variables</h2><ul><li><p>他是一個獨立的同步化 tool，跟 monitor 沒關係</p></li><li><p>Event driven</p></li><li><p>To allow a process to wait <strong>within</strong> the monitor, acondition variable must be declared, as</p><p><code>condition x, y;</code></p></li><li><p>Can be used with <code>wait()</code> and <code>signal()</code>（但是跟上面的那些毫無關係，請不要搞混，定義完全不同）</p><ul><li><p><code>x.wait()</code></p><p>有一個 event queue，所以這像是 enqueue。（上面的那個是counting）</p></li><li><p><code>x.signal()</code></p><p>像是 dequeue，把裡面的 process叫醒去工作。如果裡面沒有東西，就啥都不會發生。（如果是semaphore，值會繼續加上去）</p></li></ul></li></ul><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2016.png" /></p><ul><li><p>Dining Philosophers Example</p><ul><li>Thinking — 根本沒要吃</li><li>假設大家都是看得到彼此的狀態的（i.e. 有 Global information）</li></ul><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">monitor dp &#123;</span><br><span class="line"><span class="keyword">enum</span> &#123;thinking, hungry, eating&#125; state[<span class="number">5</span>]; <span class="comment">// current state</span></span><br><span class="line">condition self[<span class="number">5</span>]; <span class="comment">// delay eating if can’t obtain chopsticks</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">pickup</span> <span class="params">(<span class="type">int</span> i)</span>    <span class="comment">// pickup chopsticks</span></span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">putdown</span> <span class="params">(<span class="type">int</span> i)</span>   <span class="comment">// putdown chopsticks</span></span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test</span> <span class="params">(<span class="type">int</span> i)</span>      <span class="comment">// try to eat</span></span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">init</span><span class="params">()</span> </span>&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">5</span>; i++) </span><br><span class="line">state[i] = thinking;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"> <span class="function"><span class="type">void</span> <span class="title">pickup</span><span class="params">(<span class="type">int</span> i)</span> </span>&#123;</span><br><span class="line">state[i] = hungry;</span><br><span class="line"><span class="built_in">test</span>(i);               <span class="comment">// try to eat (to prevent deadlock)</span></span><br><span class="line"><span class="keyword">if</span> (state[i] != eating)  <span class="comment">// 沒成功吃到</span></span><br><span class="line">self[i].<span class="built_in">wait</span>();        <span class="comment">// wait to eat</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">putdown</span><span class="params">(<span class="type">int</span> i)</span> </span>&#123;</span><br><span class="line">  state[i] = thinking;</span><br><span class="line"></span><br><span class="line"><span class="comment">// check if neighbors are waiting to eat</span></span><br><span class="line"><span class="comment">// 叫他們起來吃飯</span></span><br><span class="line"><span class="built_in">test</span>((i+<span class="number">4</span>) % <span class="number">5</span>);</span><br><span class="line"><span class="built_in">test</span>((i+<span class="number">1</span>) % <span class="number">5</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">test</span><span class="params">(<span class="type">int</span> i)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> ((state[(i + <span class="number">4</span>) % <span class="number">5</span>] != eating) </span><br><span class="line">&amp;&amp; (state[(i + <span class="number">1</span>) % <span class="number">5</span>] != eating) <span class="comment">// 左邊和右邊有沒有在吃</span></span><br><span class="line">&amp;&amp; (state[i] == hungry)) &#123;        <span class="comment">// 和我想不想吃</span></span><br><span class="line"><span class="comment">// No neighbors are eating and Pi is hungry</span></span><br><span class="line">state[i] = eating;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 把他自己叫起（如果是 pickup call 的，這是沒有用的</span></span><br><span class="line"><span class="comment">// 但是如果是 putdown call 的，那就會搖醒睡著的）</span></span><br><span class="line">self[i].<span class="built_in">signal</span>(); </span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><ul><li><p>An illustration</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2017.png" /></p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2018.png" /></p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2019.png" /></p><figure><img src="/assets/%5BOS%5DChapter-6/Untitled%2020.png"alt="P2 test 失敗，所以去 waiting" /><figcaption aria-hidden="true">P2 test 失敗，所以去 waiting</figcaption></figure><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2021.png" /></p><figure><img src="/assets/%5BOS%5DChapter-6/Untitled%2022.png"alt="P2 被叫醒了" /><figcaption aria-hidden="true">P2 被叫醒了</figcaption></figure><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2023.png" /></p></li></ul></li></ul><h1 id="thread-programming">Thread Programming</h1><p>（考試比較不會考）</p><h2 id="pthread-lockmutex-routines">Pthread Lock/Mutex Routines</h2><p>To use mutex:</p><ul><li>Declared as of type <code>pthread_mutex_t</code></li><li>Initialized with <code>pthread_mutex_init()</code></li><li>Destroyed with <code>pthread_mutex_destroy()</code></li><li>Use <code>pthread_mutex_lock()</code> and<code>pthread_mutex_unlock()</code></li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> “pthread.h”</span></span><br><span class="line">pthread_mutex mutex;</span><br><span class="line"><span class="built_in">pthread_mutex_init</span> (&amp;mutex, <span class="literal">NULL</span>);  <span class="comment">// NULL -&gt; optional configuration</span></span><br><span class="line"><span class="built_in">pthread_mutex_lock</span>(&amp;mutex);</span><br><span class="line">**<span class="comment">// Critical Section**</span></span><br><span class="line"><span class="built_in">pthread_mutex_unlock</span>(&amp;mutex);</span><br><span class="line"><span class="built_in">pthread_mutex_destroy</span>(&amp;mutex);</span><br></pre></td></tr></table></figure><h2 id="condition-variables-cv">Condition Variables (CV)</h2><p>跟上面的一樣。</p><ul><li><p>In Pthread, CV type is a <code>pthread_cond_t</code></p><ul><li>Use <code>pthread_cond_init()</code> ****to initialize</li><li><code>pthread_cond_wait (&amp;theCV, &amp;somelock)</code></li><li><code>pthread_cond_signal (&amp;theCV)</code></li><li><code>pthread_cond_broadcast (&amp;theCV)</code> → 把 queue裡面全部的 thread 都叫醒（i.e. 對他們全部作 <code>signal</code>）</li></ul></li><li><p>Example</p><ul><li>一個 thread 在 x = 0 的時候做事</li><li>另一個負責 x--</li></ul><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2024.png" /></p><ul><li><p>一定要把 wait 和 signal 在 mutex 被 lock 的時候才能用（不然連code 都不會跑）</p><ol type="1"><li>因為 call wait 和 signal 的時候，大多會和其他 conditional variable有相依性（In this case: <code>x</code>），所以 lock起來才是合理的。</li><li>要確保 <code>cond</code> 不會有 concurrent write 的問題。</li></ol><p>⇒ 所以至少要包到他本身和他的觸發條件。</p></li><li><p>What really happens...</p><ol type="1"><li><p><code>action</code>: Lock <code>mutex</code></p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2025.png" /></p></li><li><p><code>action</code> call <code>wait</code>, put thread into sleepand <strong>release the lock</strong>. ⇒ 因為 <code>wait</code> 會直接release <code>mutex</code> （所以不是下面那行做的，是 <code>wait</code>就直接 release 掉了！）</p><p><code>counter</code> lock <code>mutex</code></p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2026.png" /></p></li><li><p><code>counter</code> go into CS and call <code>signal</code>.</p><p><code>action</code> is waked up, but thread is locked.（<code>unlock</code> 會先呼叫 <code>lock</code>確定可以跑，但顯然不行，因為 lock 還在 counter 那邊 ）</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2027.png" /></p></li><li><p><code>counter</code> call unlock.</p><p><code>action</code> Re-acquire lock and resume execution</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2028.png" /></p></li><li><p><code>action</code> release lock</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2029.png" /></p></li></ol><ul><li>另一個我們之所以要用 lock 包住的原因。</li></ul></li></ul></li></ul><h2 id="threadpool-implementation">ThreadPool Implementation</h2><ul><li><p>Task structure</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2030.png" /></p><ul><li>存 function pointer 跟 argument</li></ul></li><li><p>ThreadPool structure</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2031.png" /></p><ul><li><code>thread_count</code> — 紀錄一共有多少 threads</li><li><code>*thread</code> — threadPool</li><li><code>head</code> — <code>*queue</code> 的 head</li><li><code>tail</code> — <code>*queue</code> 的 tail</li><li><code>shutdown</code> — threadPool 是不是要結束掉了（決定要不要break while loop）</li></ul></li><li><p>Allocate thread and task queue</p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2032.png" /></p></li><li><p>Implement</p><figure><img src="/assets/%5BOS%5DChapter-6/Untitled%2033.png"alt="注意有個 mutex_lock 也會去檢查 count 是不是 0，如果是，那目前沒有工作，先睡覺（notify is our condition variable）" /><figcaption aria-hidden="true">注意有個 <code>mutex_lock</code>也會去檢查 <code>count</code> 是不是0，如果是，那目前沒有工作，先睡覺（notify is our conditionvariable）</figcaption></figure><figure><img src="/assets/%5BOS%5DChapter-6/Untitled%2034.png"alt="有事情做了，或是被 wake up 起來了，就可以做事了。 最後是 call function pointer。（注意是要放在 CS 外面，這樣才有平行度）" /><figcaption aria-hidden="true">有事情做了，或是被 wake up起來了，就可以做事了。 最後是 call function pointer。（注意是要放在 CS外面，這樣才有平行度）</figcaption></figure></li></ul><h2 id="synchronized-tools-in-java">Synchronized Tools in JAVA</h2><ul><li><p>Synchronized Methods (Monitor)</p><p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SynchronizedCounter</span> &#123; </span><br><span class="line"><span class="keyword">private</span> <span class="type">int</span> <span class="variable">c</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">increment</span><span class="params">()</span> &#123; c++; &#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">decrement</span><span class="params">()</span> &#123; c--; &#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="type">int</span> <span class="title function_">value</span><span class="params">()</span> &#123; <span class="keyword">return</span> c; &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>加上 synchronized 就可以保證只有一個才操作。所以可以看到有動到<code>c</code> 的都有加。如果沒有動到 share data的，可以不用加，增加平行度。</p></li><li><p>Synchronized Statement (Mutex Lock)</p><p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">synchronized</span>(p1)</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">10</span>; <span class="comment">// statement without locking requirement</span></span><br><span class="line">p1.display(s1);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p></li></ul><h2 id="review-slides-4">Review Slides (4)</h2><ul><li>Bounded-buffer problem?</li><li>Reader-Writer problem?</li><li>Dining Philosopher problem?</li><li>What is monitor and why need monitor?</li></ul><h1 id="atomic-transactions">Atomic Transactions</h1><p>（考試不太會提）</p><ul><li>System Model<ul><li>Transaction: 一系列的 operation</li><li>Atomic Transaction: 需要一次完成 transaction，all or nothing</li><li>DB 很容易需要</li></ul></li><li>File I/O Example<ul><li>Transaction 是一連串的 read and write</li><li>像是 version control 的工具，需要有 commit（成功）、abort（失敗）、rolled back（失敗後要 undo）</li><li>所以重點是要有 log<ul><li>因為有 log 才能回推重建</li><li>也叫做 checkpoint</li><li>存在 secondary storage</li></ul></li><li>也會有 checkpoints<ul><li>還原點，上一個 commit 的點</li><li>說不定會直接不 undo，然後 apply checkpoint</li></ul></li></ul></li></ul><h2 id="review-slides-5">Review Slides (5)</h2><ul><li>What is atomic transaction?</li><li>Purpose of commit, abort, rolled-back?</li><li>How to use log and checkpoints?</li></ul><h1 id="textbook-problem-set">Textbook Problem Set</h1><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2035.png" /></p><p><img src="/assets/%5BOS%5DChapter-6/Untitled%2036.png" /></p><div class="note warning"><p>此筆記為清華大學周志遠教授作業系統之課堂筆記，所有內容及圖片皆取材於課堂內容。<br />如內容有誤，歡迎來信 <ahref="mailto:mail@arui.dev">mail@arui.dev</a>。</p></div>]]></content>
    
    
    <summary type="html">&lt;div class=&quot;note default&quot;&gt;&lt;p&gt;&lt;a
href=&quot;https://arui-tw.notion.site/Chapter-6-Process-Synchronization-dc2fdd2951b047f78a39377759ebe90c&quot;&gt;Notion
好讀版&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id=&quot;background&quot;&gt;Background&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;因為有 share 的 data，會被多個 content 去用他，所以需要&lt;/li&gt;
&lt;li&gt;就算只有一個 core，也會有 Concurrent 的問題（因為會有 content
switch）&lt;/li&gt;
&lt;li&gt;重點就是他們 execute 的 order&lt;/li&gt;
&lt;li&gt;Consumer &amp;amp; Producer Problem
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;用 counter 去記還有幾個空位&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Producer&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	nextItem = &lt;span class=&quot;built_in&quot;&gt;getItem&lt;/span&gt;( );&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (counter == BUFFER_SIZE);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	buffer[in] = nextItem;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	in = (in + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) % BUFFER_SIZE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	counter++;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (counter == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;) ;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	item = buffer[out];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	out = (out + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;) % BUFFER_SIZE;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	counter--;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;但是 counter 會是這兩隻 thread
共用的東東，所以會出現不一致的問題：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;counter++&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;move ax, counter&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;add  ax, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;move counter, ax&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;counter--&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;move bx, counter&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sub  bx, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;move counter, bx&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;但是…如果是這樣呢？（counter initially is 5）&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;producer: move ax, counter   &lt;span class=&quot;comment&quot;&gt;// ax = 5&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;producer: add ax, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;          &lt;span class=&quot;comment&quot;&gt;// ax = 6&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;context &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;consumer: move bx, counter   &lt;span class=&quot;comment&quot;&gt;// bx = 5&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;consumer: sub bx, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;          &lt;span class=&quot;comment&quot;&gt;// bx = 4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;context &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;producer: move counter, ax   &lt;span class=&quot;comment&quot;&gt;// counter = 6&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;context &lt;span class=&quot;keyword&quot;&gt;switch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;consumer: move counter, bx   &lt;span class=&quot;comment&quot;&gt;// counter = 4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;不過如果不是 preemptive 就不會有這個問題了。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;race-condition&quot;&gt;Race Condition&lt;/h2&gt;
&lt;aside&gt;
&lt;p&gt;📖 多個 process 操作 shared data
concurrently，結果會取決於最後完成的人。（這是描述一個問題點，所以是因為有
race condition，要用同步化解決）&lt;/p&gt;
&lt;/aside&gt;
&lt;ul&gt;
&lt;li&gt;Single processor 的可以用 disable interrupt 或 non-preemptive CPU
來解決。&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Operating System Notes" scheme="https://blog.arui.dev/categories/Operating-System-Notes/"/>
    
    
    <category term="Operating System" scheme="https://blog.arui.dev/tags/Operating-System/"/>
    
    <category term="Notes" scheme="https://blog.arui.dev/tags/Notes/"/>
    
  </entry>
  
  <entry>
    <title>[OS] Chapter 5 — Process Scheduling</title>
    <link href="https://blog.arui.dev/[OS]Chapter-5/"/>
    <id>https://blog.arui.dev/[OS]Chapter-5/</id>
    <published>2022-01-31T10:05:24.000Z</published>
    <updated>2022-02-01T14:21:49.380Z</updated>
    
    <content type="html"><![CDATA[<div class="note default"><p><ahref="https://arui-tw.notion.site/Chapter-5-Process-Scheduling-ade82d3c9cb94423b787100fbce02fd1">Notion好讀版</a></p></div><h1 id="basic-concepts">Basic Concepts</h1><p>因為 multiprogramming 所以才要 scheduling。</p><h2 id="cpu-io-burst-cycle">CPU-I/O burst cycle</h2><p>→ 東西要嘛在 CPU 要嘛在 I/O</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled.png" /></p><ul><li><p>所以每一個 process 就切成在 CPU burst 和在 I/O burst</p></li><li><p>I/O-bound program → 大部分在做 I/O</p><p>⇒ 不等於 I/O burst 的 cycle 數比 CPU多（數量應該要是一樣的，因為一個做完接另一個），應該要是一個 burst要很久。</p></li><li><p>CPU-bound program → 大部分在做 CPU</p></li><li><p>CPU 大多是短的 burst 很多</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%201.png" /></p></li></ul><h2 id="cpu-scheduler">CPU Scheduler</h2><p>Ready state → Running state</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%202.png" /></p><p>下面都假設是 single core，只有單一隻程式</p><span id="more"></span><h3 id="preemptive-vs.-non-preemptive">Preemptive vs.Non-preemptive</h3><ul><li>Preemptive → 一個 process 可以在 CPU burst 中間被打斷</li><li>Non-preemptive → 一個 process 不能在 CPU burst中間被打斷，一定要做完的</li><li>CPU scheduling 要做事的時間點：<ol type="1"><li><font color=#A865C9>A process switch from running to waiting → CPU空下來了，可以加東西囉</font></li><li>A process switch from running to ready（可能是 timer到了，所以被丟過去了）→ CPU 空下來了，可以加東西囉</li><li>A process switch from waiting to ready → 看看有沒有更重要，需要就把running 的拿掉換他</li><li><font color=#A865C9>A process terminates → CPU空下來了，可以加東西囉</font></li></ol><ul><li>紫色是 Non-preemptive 的 scheduler 只能做的事</li></ul></li><li>大部分都是 preemptive。（Windows, Mac OS）</li><li>Preemptive issue<ul><li>會打斷東西，所以可能會 raise condition（如果不打斷就不會產生）</li><li>會影響到 OS 需不需要處理 synchronisation 的問題</li><li>Unix solution: 進到 kernel space 就 disable 2 和 3（就會變成non-preemptive）</li></ul></li></ul><h2 id="dispatcher">Dispatcher</h2><ul><li>把 scheduler 選出來的東西丟到 CPU 裡面的苦工。（Switchingcontext...）</li><li>要很有效率</li></ul><h1 id="scheduling-algorithms">Scheduling Algorithms</h1><ul><li>Scheduling Criteria → 定義效能的指標<ul><li>CPU utilization<ul><li>0% ~ 100% (per core)</li><li>通常大概會在 40% ~ 90% 之間</li></ul></li><li>Throughput<ul><li>每單位時間可以完成多少工作（processes）</li><li>High throughput computer system → 目標就是要最大化 through 的computer system</li><li>很常見，比 utilization 重要（對 user 來講比較有感覺）</li></ul></li><li>Turnaround time<ul><li>單一 process 的角度來量測</li><li>進到 new 到 terminate 的時間（submission ~ completion）</li><li>通常會看平均、最大值、最小值、distribution 等等</li></ul></li><li>Waiting time<ul><li>在 ready queue 的總時間（不包括 waiting time）</li><li>是純粹因為 scheduling 的原因所以不能執行</li></ul></li><li>Response time<ul><li>new 到第一次回應（第一次進到 running）</li></ul></li></ul></li></ul><h2 id="first-come-first-served-fcfs-scheduling">First-Come,First-Served (FCFS) scheduling</h2><p>先來先排</p><p>會給 CPU burst time，根據他們進來的順序</p><ul><li><p>Example</p><ul><li>P1(24), P2(3), P3(3)</li></ul><p><img src="/assets/%5BOS%5DChapter-5/Untitled%203.png" /></p><ul><li>Waiting time: P1 = 0, P2 = 24, P3 = 27</li><li>Average Waiting Time (AWT): (0 + 24 + 27) / 3 = 17</li></ul></li><li><p>Convoy effect (Head of line blocking):可以很快執行的被要跑很久的擋住了</p></li></ul><h2 id="shortest-job-first-sjf-scheduling">Shortest-Job-First (SJF)scheduling</h2><ul><li><p>Optimal solution → minimum average waiting time</p></li><li><p>最短 CPU burst time 的先做</p></li><li><p>Two schemes</p><ol type="1"><li>Non-preemptive</li><li>Preemptive</li></ol></li><li><p>Non-preemptive example</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%204.png" /></p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%205.png" /></p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%206.png" /></p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%207.png" /></p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%208.png" /></p></li><li><p>有時候 ready queue 會是空的，那 CPU 就 idle。</p></li><li><p>AWT 不要算到 CPU idle 的時間。</p></li><li><p>Preemptive example</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%209.png" /></p><figure><img src="/assets/%5BOS%5DChapter-5/Untitled%2010.png"alt="7-2 &gt; 4 → content switch!  一般的方式可能是把 P1 加回 Ready queue 裡面，然後再挑最短的出來" /><figcaption aria-hidden="true">7-2 &gt; 4 → content switch!<br>一般的方式可能是把 P1 加回 Ready queue裡面，然後再挑最短的出來</figcaption></figure><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2011.png" /></p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2012.png" /></p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2013.png" /></p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2014.png" /></p><figure><img src="/assets/%5BOS%5DChapter-5/Untitled%2015.png"alt="比上面的更短" /><figcaption aria-hidden="true">比上面的更短</figcaption></figure></li><li><p>但是因為沒有 futureknowledge，所以實作不出來（所以會預測，但是失準就 GG）</p><ul><li><p>Approximate SJF: time series,用歷史和上次的結果去調整比例來算</p><p><span class="math display">\[  \tau_{n+1}=\alpha t_n+(1-\alpha)\tau_n  \]</span></p><ul><li><p><span class="math inline">\(\tau\)</span> is the history and<span class="math inline">\(t\)</span> is the new one</p></li><li><p><span class="math inline">\(\alpha\)</span> usually set as <spanclass="math inline">\(1/2\)</span></p></li><li><p>Example</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2016.png" /></p><p>We guess 10 for the first time.</p></li></ul></li></ul></li></ul><h2 id="priority-scheduling">Priority Scheduling</h2><ul><li>每個 process 就有一個 priority的值（要怎麼決定，啥時決定，都可以），然後就照那個決定</li><li>最 general 的，上面的兩個也可以說是 priority scheduling</li><li>Problem:<ul><li>Starvation: 可能有 process 會永遠沒有排程到<ul><li>Solution: aging → 等越久，priority 越高</li></ul></li></ul></li></ul><h2 id="round-robin-rr-scheduling">Round-Robin (RR) Scheduling</h2><ul><li><p>每一個 process 都只能執行一定的時間（a.k.a time quantum, usually10 ~ 100 ms），時間到就被踢出來重新排隊</p></li><li><p>容易實作，公平</p></li><li><p>Performance</p><ul><li>TQ too large → FIFO (FCFS)<ul><li>如果不在乎 fairness，那這樣也 OK</li></ul></li><li>TQ too small → (context switch) overhead increase<ul><li>如果 CPU 沒什麼人在用，那這樣也 OK</li></ul></li><li>所以就看系統需求</li></ul></li><li><p>Example</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2017.png" /></p></li><li><p>Response time 通常會是最小的，但是 turn around time通常會很大</p></li></ul><h2 id="multilevel-queue-scheduling">Multilevel Queue Scheduling</h2><ul><li><p>上面都是 single queue</p></li><li><p>現在這個有很多 ready queue，一個 process 只會進到其中一個queue</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2018.png" /></p></li><li><p>每一個單一 queue都可以用上面那些解法，我們現在要解決的是怎麼從這麼多 queue 中挑哪一個queue 來 deqeue</p><ul><li>Fixed priority scheduling: 根據 queue 的 priority 開始挑<ul><li>一樣會有 starvation → 最上面一定要清完才能作下面的，最下面的 queue可能會排不到</li></ul></li><li>Time slice: 每一個 queue 會有各自被選中的機率，選中就從那邊dequeue</li></ul></li><li><p>我們要決定哪一個 process 要加到哪個 queue，但是要在 <strong>run之前</strong>就做決定，且加進去就會一直待在裡面，所以可能會東西作一作就變成不應該在那個queue 的，這樣不好。所以有下面的：</p></li></ul><h2 id="multilevel-feedback-queue-scheduling">Multilevel Feedback QueueScheduling</h2><ul><li><p>Queues 不會分是要作哪種 process，所以 process 可以在 queues中移動。（所以叫 feedback）</p></li><li><p>所以 Higher level 一定都會先被執行（可以作 aging to preventstarvation）</p></li><li><p>所以我們要做的事情就變成要決定誰會移到哪個queue（跟上面要做的事完全不同）</p></li><li><p>幾乎都是根據 I/O 的時間來排，i.e. <strong>I/O-bound的程式會放到上面的 queue。</strong>（因為通常 I/O-bound 的程式 CPU通常會跑比較快）</p></li><li><p>Example</p><ul><li>移動條件：如果超過 TQ，就往後踢</li></ul><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2019.png" /></p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2020.png" /></p></li><li><p>所以我們需要決定</p><ul><li>有幾個 queues</li><li>每個 queue 用哪種 single queue 的演算法</li><li>什麼時候 process 要移動</li></ul></li></ul><h2 id="evaluation-methods">Evaluation Methods</h2><ul><li>Deterministic modeling — Given 已知且固定的input，去比較各個方式（超沒用，通常當例子用）</li><li>Queueing model — 用數學（Queuetheory）去算（不是很準，偏向理論）</li><li>Simulation — 模擬然後得到結果（這只有部分功能）</li><li>Implementation — 就實作出來（這已經完整了）</li></ul><h2 id="review-slide-i">Review Slide (I)</h2><ul><li>Preemptive scheduling vs Non-preemptive scheduling?</li><li>Issues of preemptive scheduling</li><li>Turnaround time? Waiting time? Response time? Throughput?</li><li>Scheduling algorithms<ul><li>FCFS</li><li>Preemptive SJF, Nonpreemptive SJF</li><li>Priority scheduling</li><li>RR</li><li>Multilevel queue</li><li>Multilevel feedback queue</li></ul></li></ul><h1 id="special-scheduling-issues">Special Scheduling Issues</h1><h2 id="multi-processor-scheduling">Multi-Processor Scheduling</h2><ul><li>硬體會跟 scheduler 講說他需要多少，就拿給他</li><li>Asymmetric multiprocessing<ul><li>會有一個 centralise 的傢伙在處理誰要去哪</li><li>就沒有 synchronise 的問題</li><li>但是會浪費一個 core 在處理</li></ul></li><li>Symmetric multiprocessing (SMP)<ul><li>直接開搶，所以需要 lock 來處理 synchronise 的問題</li></ul></li></ul><h3 id="processor-affinity">Processor affinity</h3><p>把 process 綁在一個 CPU 上（不同 CPU burst 可能會在不同 core上）（是為了要處理資料在換 core 的時候資料要重新 cache）</p><ul><li>Type:<ul><li>soft affinity<ul><li>如果有空的，就還是會去用</li></ul></li><li>Hard affinity<ul><li>就算有空的， 也不會用</li></ul></li></ul></li><li>如果系統的 loading 沒有很高，這是一定有好處沒壞處的，但是如果很多process 在搶 core，那這就沒啥用了。</li></ul><h3 id="numa-and-cpu-scheduling">NUMA and CPU Scheduling</h3><ul><li>NUMA (non-uniform memory access)<ul><li>有些 CPU 離某些 memory 比較近，所以還要把 process 放到離 CPU比較近的 memory</li></ul></li></ul><h3 id="load-balancing">Load-balancing</h3><ul><li><p>Push Migration — 把工作推出去，如果 loading輕，就用這個去丟工作</p></li><li><p>Pull Migration — 把工作拉進來，如果 loading重，就用這個去丟工作</p><p>Load balancing often counteracts the benefits of processor affinity(355)</p></li></ul><h2 id="multi-core-processor-scheduling">Multi-Core ProcessorScheduling</h2><ul><li><p>Multi-core Processor — memory stall: 需要等 access memory的時間</p></li><li><p>Multi-threaded multi-core systems</p><ul><li>把上面等 memory access 的時間拿來做事</li></ul><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2021.png" /></p><ul><li>Two ways:<ol type="1"><li>fine-grained: 把所有 stage的東西都記下來，所以東西不會掉。但是就需要很多硬體資源去記。（快，成本高）</li><li>coarse-grained: 會 flush 不用的東西</li></ol></li></ul></li><li><p>Scheduling for Multi-threaded multi-core systems</p><ul><li>Hardware 跟 software 說要幾個 process，然後 software 就給他</li><li>要怎麼去處理要來的 process（執行在哪個 core）就給 hardware 決定</li></ul></li></ul><h2 id="real-time-scheduling">Real-Time Scheduling</h2><p>Real-time does not mean speed, but keeping deadlines</p><ul><li>Soft real-time — 希望可以不要 miss deadline，但是 miss也不會炸開</li><li>Hard real-time — 絕對不能 miss deadline</li></ul><h3 id="real-time-scheduling-algorithms">Real-Time SchedulingAlgorithms</h3><p>比前面多了 period 的參數 →每過多久就會重新出現，要在下一次出現前做完這次的。（E.g., (0, 4, 10) →0，10，20 都會出現一次）</p><ul><li>FCFS — Non-RTS</li><li>Rate-Monotonic (RM) Scheduling<ul><li><p>Static (Fixed) → 跑得時候不會改變</p></li><li><p>Shortest period first</p></li><li><p>Example</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2022.png" /></p></li></ul></li><li>Earliest-Deadline-First (EDF) algorithm<ul><li><p>Dynamic → 跑得時候，每一個的 priority 會變動（因為離 deadline的時間會變近）</p></li><li><p>Early deadline first</p></li><li><p>Miss deadline 會被 bound 住</p></li><li><p>Example</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2023.png" /></p></li></ul></li></ul><h2 id="review-slide-ii">Review Slide (II)</h2><ul><li>What is Processor affinity?</li><li>Real-time scheduler<ul><li>Rate-Monotonic</li><li>Earliest deadline first</li></ul></li></ul><h1 id="scheduling-case-study">Scheduling Case Study</h1><h2 id="solaris">Solaris</h2><ul><li>Priority-based multilevel feedback queue scheduling</li><li>六個 class — 更像是六個queue，反正最上面的一定會先做。裡面小的會再自己排序</li></ul><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2024.png" /></p><ul><li>Example<ul><li>the <strong>higher</strong> the priority, the<strong>smaller</strong> the time slice（因為我們希望 priority 高的，CPUburst time 是短的，所以很快搶到就要很快放掉）<ul><li>Time quantum expired: 只要使用超過你的 timeslice，就根據下表調整你的 priority。（因為感覺你是更 CPU burst 的）</li><li>Return from sleep: 從 sleep (i.e. I/O wait) 回來就提升priority。（因為可以縮短等待時間）</li></ul><img src="/assets/%5BOS%5DChapter-5/Untitled%2025.png" /></li></ul></li></ul><h2 id="windows">Windows</h2><p>跟剛剛的差不多</p><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2026.png" /></p><h2 id="linux">Linux</h2><ul><li><p>值越小，priority 越高</p></li><li><p>分成兩個 class 而已</p></li><li><p>Priority 高的，分到的 time quantum 越大</p><p>⇒ 因為這邊的 time quantum 是 budget 的概念，只要用完就會被丟到waiting queue</p></li><li><p>所以他是用比較 fairness 的作法</p></li></ul><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2027.png" /></p><ul><li>Algorithm<ul><li>一開始大家都在 active array，然後時間到就被丟到 expiredarray。（這樣就算是 low priority 的也可以被做到）</li><li>最後 active array 被清空了就把兩個 array 的指標對調。</li><li>所以他是一輪一輪的做。</li></ul><img src="/assets/%5BOS%5DChapter-5/Untitled%2028.png" /></li></ul><h1 id="textbook-questions">Textbook Questions</h1><p><img src="/assets/%5BOS%5DChapter-5/Untitled%2029.png" /></p><h1 id="qa">QA</h1><ul><li>What is CPU-burst?<ul><li>程式正在做 CPU 的 instruction，除此之外的時間都是 I/O-burst</li></ul></li><li>Preemptive vs. Non-preemptive?<ul><li>Preemptive：在 CPU burst 間 scheduler 可以 interrupt 做 scheduling的動作</li><li>Non-preemptive：在 CPU burst 間 scheduler 不能 interrupt 做scheduling 的動作（但是 hardware 還是可以 interrupt 的）</li></ul></li></ul><div class="note warning"><p>此筆記為清華大學周志遠教授作業系統之課堂筆記，所有內容及圖片皆取材於課堂內容。<br />如內容有誤，歡迎來信 <ahref="mailto:mail@arui.dev">mail@arui.dev</a>。</p></div>]]></content>
    
    
    <summary type="html">&lt;div class=&quot;note default&quot;&gt;&lt;p&gt;&lt;a
href=&quot;https://arui-tw.notion.site/Chapter-5-Process-Scheduling-ade82d3c9cb94423b787100fbce02fd1&quot;&gt;Notion
好讀版&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id=&quot;basic-concepts&quot;&gt;Basic Concepts&lt;/h1&gt;
&lt;p&gt;因為 multiprogramming 所以才要 scheduling。&lt;/p&gt;
&lt;h2 id=&quot;cpu-io-burst-cycle&quot;&gt;CPU-I/O burst cycle&lt;/h2&gt;
&lt;p&gt;→ 東西要嘛在 CPU 要嘛在 I/O&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/%5BOS%5DChapter-5/Untitled.png&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;所以每一個 process 就切成在 CPU burst 和在 I/O burst&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I/O-bound program → 大部分在做 I/O&lt;/p&gt;
&lt;p&gt;⇒ 不等於 I/O burst 的 cycle 數比 CPU
多（數量應該要是一樣的，因為一個做完接另一個），應該要是一個 burst
要很久。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CPU-bound program → 大部分在做 CPU&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CPU 大多是短的 burst 很多&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/%5BOS%5DChapter-5/Untitled%201.png&quot; /&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;cpu-scheduler&quot;&gt;CPU Scheduler&lt;/h2&gt;
&lt;p&gt;Ready state → Running state&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/assets/%5BOS%5DChapter-5/Untitled%202.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;下面都假設是 single core，只有單一隻程式&lt;/p&gt;</summary>
    
    
    
    <category term="Operating System Notes" scheme="https://blog.arui.dev/categories/Operating-System-Notes/"/>
    
    
    <category term="Operating System" scheme="https://blog.arui.dev/tags/Operating-System/"/>
    
    <category term="Notes" scheme="https://blog.arui.dev/tags/Notes/"/>
    
  </entry>
  
  <entry>
    <title>WebSocket</title>
    <link href="https://blog.arui.dev/WebSocket/"/>
    <id>https://blog.arui.dev/WebSocket/</id>
    <published>2021-05-12T09:50:24.000Z</published>
    <updated>2022-02-01T15:10:57.026Z</updated>
    
    <content type="html"><![CDATA[<div class="note default"><p><ahref="https://arui-tw.notion.site/WebSocket-4aae9807cbc94e69b3e91fe69c58262b">Notion好讀版</a></p></div><p>網路溝通可以分成兩種主要的 API</p><ul><li>Web Service APIs (e.g. SOAP, JSON-RPC, XML-RPC, REST)</li><li>Web Socket APIs</li></ul><h1 id="http">HTTP</h1><p><ahref="https://factoryhr.medium.com/http-2-the-difference-between-http-1-1-benefits-and-how-to-use-it-38094fa0e95b">HTTP/2:the difference between HTTP/1.1, benefits and how to use it</a></p><h2 id="rest-representational-state-transfer">REST (REpresentationalState Transfer)</h2><p>→ 幫 HTTP 套規則</p><ul><li>GET → 取得資料</li><li>PUT → 修改資料</li><li>POST → 新增資料</li><li>DELETE → 刪除資料</li></ul><span id="more"></span><h2 id="http-polling輪詢">HTTP polling(輪詢)</h2><p>可以用兔子（Client）和店老闆（Server）來想像。</p><h3 id="http-short-polling">HTTP Short Polling</h3><p>需要一直問。像是兔子一直站在店旁邊不停地問「有紅蘿蔔嗎？」，每問一次老闆就要回他一次「沒有。」或是「有。」老闆回完話後，兔子過一陣子之後就會再問一次「有紅蘿蔔嗎？」所以整個流程就會像：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">00:00:00 兔子 -&gt; 有紅蘿蔔嗎？</span><br><span class="line">00:00:01 老闆 -&gt; 沒有。</span><br><span class="line">00:00:03 兔子 -&gt; 有紅蘿蔔嗎？</span><br><span class="line">00:00:04 老闆 -&gt; 沒有。</span><br><span class="line">00:00:06 兔子 -&gt; 有紅蘿蔔嗎？</span><br><span class="line">00:00:07 老闆 -&gt; 有，拿去。</span><br><span class="line">00:00:09 兔子 -&gt; 有紅蘿蔔嗎？</span><br></pre></td></tr></table></figure><p>這種方法雖然不會占用 Client 和 Server過多的資源，但是因為他每過一陣子才會再重新問一次，所以也不能拿到即時的資料。還有就是在來回傳輸的過程中還是會頻繁的浪費網路資源，還有可能什麼都沒拿到。</p><h3 id="http-long-polling">HTTP Long Polling</h3><p>這個方法就是老闆生氣了，不想要理兔子了，所以他決定等到貨到了再跟兔子說有紅蘿蔔了。但是如過或太久沒有到，久到他都氣消了，他還是會跟兔子說「沒有」。所以對話會變成下面這樣：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">00:00:00 兔子 -&gt; 有紅蘿蔔嗎？</span><br><span class="line">00:00:10 老闆 -&gt; 沒有。</span><br><span class="line">00:00:10 兔子 -&gt; 有紅蘿蔔嗎？</span><br><span class="line">00:00:13 老闆 -&gt; 有，拿去。</span><br><span class="line">00:00:13 兔子 -&gt; 有紅蘿蔔嗎？</span><br></pre></td></tr></table></figure><p>這個的缺點就是老闆和兔子同時都被耽擱了，老闆在等著要回復兔子，而兔子也等著老闆的回覆。也就是說，前端和後端的通訊同時都被卡住了。還有如果資料更新的很頻繁，這個方法就會相對的很沒有效率，因為每次老闆都會馬上回答有貨了，而不能累積很多再一次給兔子。但他的優點就在於這種方法是沒有延遲的，因為老闆一拿到貨就會馬上跟兔子說有紅蘿蔔。</p><h2 id="http-streaming">HTTP Streaming</h2><p>這次換兔子覺得麻煩了，所以他跟老闆說，我就在這邊等著，只要貨一有情況就要馬上跟我說喔，等我拿夠了，我會再跟你說。所以對會變成這樣：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">00:00:00 兔子 -&gt; 有紅蘿蔔嗎？</span><br><span class="line">00:00:01 老闆 -&gt; 等一下喔。</span><br><span class="line">00:00:02 老闆 -&gt; 貨快到了。</span><br><span class="line">00:00:03 老闆 -&gt; 有，拿去。</span><br><span class="line">00:00:03 老闆 -&gt; 正在等下一次送貨。</span><br><span class="line">00:00:04 老闆 -&gt; 貨快到了。</span><br><span class="line">00:00:05 老闆 -&gt; 有，拿去。</span><br><span class="line">00:00:05 老闆 -&gt; 正在等下一次送貨。</span><br><span class="line">00:00:06 兔子 -&gt; 夠了，謝啦。</span><br></pre></td></tr></table></figure><p>這個方法最大的問題是由於他是建立在 HTTP協定上的一種傳輸機制，所以有可能會因為代理伺服器（proxy）或防火牆（firewall）將其中的資料存放在緩衝區中，造成資料回應上的延遲。</p><h3 id="sse-server-sent-events-eventsource">SSE (Server Sent Events /EventSource)</h3><p>這個方法和上一個類似，只是兔子覺得老闆太多廢話了，所以他跟老闆說，不要什麼都跟我說，只要有貨再跟我說就好了。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">00:00:00 兔子 -&gt; 有紅蘿蔔嗎？</span><br><span class="line">00:00:03 老闆 -&gt; 有，拿去。</span><br><span class="line">00:00:05 老闆 -&gt; 有，拿去。</span><br><span class="line">00:00:06 兔子 -&gt; 夠了，謝啦。</span><br></pre></td></tr></table></figure><p>這兩個都共有的問題 MDN 上有提到</p><blockquote><p>當連線不是透過 HTTP/2 時，SSE會受到最大連線數限制所苦，尤其當開啟多個分頁。每個瀏覽器有自己的限制數而且被限制在很低的數量（6）。</p></blockquote><p>但是透過 HTTP/2 就沒差了。但是還是有一些<ahref="https://caniuse.com/eventsource">瀏覽器</a>不支援 SSE。</p><h2 id="websockets">WebSockets</h2><p>過了這麼久，兔子和老闆都變成朋友了。所以他們無話不談，誰都可以自由的溝通。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">00:00:00 兔子 -&gt; 有紅蘿蔔嗎？</span><br><span class="line">00:00:01 老闆 -&gt; 等一下喔。</span><br><span class="line">00:00:01 兔子 -&gt; 好啊。</span><br><span class="line">00:00:03 老闆 -&gt; 有貨了，拿去。</span><br><span class="line">00:00:03 老闆 -&gt; 正在等下一次送貨。</span><br><span class="line">00:00:04 兔子 -&gt; 這是甚麼口味阿。</span><br><span class="line">00:00:04 老闆 -&gt; 我不知道欸，蘿蔔口味吧。</span><br><span class="line">00:00:05 老闆 -&gt; 貨快到了。</span><br><span class="line">00:00:05 兔子 -&gt; 太棒了，超好吃的欸。</span><br><span class="line">00:00:06 兔子 -&gt; 但是我吃夠了，謝啦。</span><br></pre></td></tr></table></figure><p>但實際上，老闆跟兔子還是要先培養感情才能這樣輕鬆的溝通的，所以他們一開始還是會透過原本HTTP 的方式來連線。</p><p><img src="/assets/WebSocket/Untitled.png" /></p><p>這就分別是 Client 和 Server 會傳給對方的訊息。Client 會傳送要求Upgrade 到 websocket 的請求和 websocket 的 Key 等資料。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">GET /chat HTTP/1.1</span><br><span class="line">Host: example.com:8000</span><br><span class="line">Upgrade: websocket</span><br><span class="line">Connection: Upgrade</span><br><span class="line">Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==</span><br><span class="line">Sec-WebSocket-Version: 13</span><br></pre></td></tr></table></figure><p>如果 Server 端沒有問題，他也會回傳可以 Upgrade的訊息。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 101 Switching Protocols</span><br><span class="line">Upgrade: websocket</span><br><span class="line">Connection: Upgrade</span><br><span class="line">Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=</span><br></pre></td></tr></table></figure><p>然後因為 WebSocket 是在另一個通訊方式下溝通的，所以他並不會占用原本用HTTP 溝通的管道。</p><p><a href="https://www.youtube.com/watch?v=1BfCnjr_Vjg">WebSockets in100 Seconds &amp; Beyond with Socket.io</a></p>]]></content>
    
    
    <summary type="html">&lt;div class=&quot;note default&quot;&gt;&lt;p&gt;&lt;a
href=&quot;https://arui-tw.notion.site/WebSocket-4aae9807cbc94e69b3e91fe69c58262b&quot;&gt;Notion
好讀版&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;網路溝通可以分成兩種主要的 API&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Web Service APIs (e.g. SOAP, JSON-RPC, XML-RPC, REST)&lt;/li&gt;
&lt;li&gt;Web Socket APIs&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;http&quot;&gt;HTTP&lt;/h1&gt;
&lt;p&gt;&lt;a
href=&quot;https://factoryhr.medium.com/http-2-the-difference-between-http-1-1-benefits-and-how-to-use-it-38094fa0e95b&quot;&gt;HTTP/2:
the difference between HTTP/1.1, benefits and how to use it&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;rest-representational-state-transfer&quot;&gt;REST (REpresentational
State Transfer)&lt;/h2&gt;
&lt;p&gt;→ 幫 HTTP 套規則&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GET → 取得資料&lt;/li&gt;
&lt;li&gt;PUT → 修改資料&lt;/li&gt;
&lt;li&gt;POST → 新增資料&lt;/li&gt;
&lt;li&gt;DELETE → 刪除資料&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Tech Share" scheme="https://blog.arui.dev/categories/Tech-Share/"/>
    
    
    <category term="Notes" scheme="https://blog.arui.dev/tags/Notes/"/>
    
  </entry>
  
</feed>
