--- title: 看漫畫學 Linux image: https://i.imgur.com/jJhfAiH.png description: 本共藉由 {turnoff.us} 的一幅漫畫,介紹 Linux 核心加上關鍵應用程式的組合 tags: LINUX KERNEL, LKI --- # 看漫畫學 Linux > 導讀: [jserv](http://wiki.csie.ncku.edu.tw/User/jserv) Daniel Stori 經營的網站 [{turnoff.us}](https://turnoff.us/) 提供一系列關於資訊技術的漫畫,其中 [inside the linux kernel](https://turnoff.us/geek/inside-the-linux-kernel/) 生動地展現 Linux 核心的部分機制和相關的套件。本文嘗試解說這幅漫畫,全貌如下: (原網站提供解析度更高的圖片) ![image](https://hackmd.io/_uploads/Sy9PfS1cT.png) 漫畫以房屋的側面剖面視角,以房屋為載體,小企鵝、小狗、小精靈等成員組為大家庭,各自分工,藉此展現 Linux。由於漫畫針對 Linux 核心的比重不算高,本文標題變更為通用的 Linux 系統,即核心加上關鍵應用程式的組合,並搭配 Daniel Stori 相關的漫畫進行解說。 小企鵝的名字是 Tux - [(T)orvalds (U)ni(X)](http://lkml.iu.edu/hypermail/linux/kernel/9606.1/0175.html),它是 Linux 的吉祥物。會選小企鵝當作 Linux 核心的吉祥物,只是[因為 Linus Torvalds 喜歡企鵝](http://lkml.iu.edu/hypermail/linux/kernel/9605.1/0457.html),而非企鵝具有特殊或象徵其他意義。 > 延伸閱讀: [The Story Behind Tux the Penguin](https://www.wired.com/2001/03/the-story-behind-tux-the-penguin/) ![image](https://hackmd.io/_uploads/HJ2_MH15p.png) > Linus Torvalds 與他辦公室內滿滿的企鵝玩偶。 > 圖片來源: [Linus Torvalds Guided Tour of His Home Office](https://youtu.be/SOXeXauRAm0) 以下術語標注於漫畫中: * file system (檔案系統) * process table (行程表) * httpd process (httpd 行程,即網頁伺服器行程) * watchdog process (看門狗行程) * ssh daemon (ssh 伺服器) * cron (執行週期性任務 [cron](https://man7.org/linux/man-pages/man8/cron.8.html) 的背景程式) * wine process (執行 [Wine](https://www.winehq.org/) 的行程) * pipe (即 [UNIX Pipeline](https://en.wikipedia.org/wiki/Pipeline_(Unix))) * terminals and terminal processes (終端機和其行程) ## 地下室 地下室擺放著一排又一排的檔案櫃,檔案櫃裡放置著檔案 (file),由此隱喻檔案系統對於 Linux 核心,乃至於泛 UNIX 作業系統的重要性 —— 檔案系統是 UNIX 風格的作業系統的基底。 ![image](https://hackmd.io/_uploads/Hkk9GB15a.png) 左上角,有隻胸前掛著牌號為 `421` 的小企鵝,它表示著 PID ([Process ID](https://en.wikipedia.org/wiki/Process_identifier),行程 ID) 為 `421` 的行程,它正在查看檔案系統裡頭某個檔案,換言之,系統中有個行程正在存取檔案系統。 > 依據某些心靈修行領域的說法,"421" 是個天使數字,不過這裡的行程編號不該因數字而有獨特之處。 右下角有隻小狗,它有敏銳的嗅覺,對應到監控 Linux 檔案系統和一系列服務的 [watchdog](https://linux.die.net/man/8/watchdog)。 ### 通往檔案系統 剖面圖的左上角 (最裡頭的區域),也就是中央大廳和地下室交界處,出現標注 `FS` 的向下樓梯 ![image](https://hackmd.io/_uploads/BkYczHkca.png) `FS` 是 file system 的簡稱,這表示行程可藉由該樓梯,存取到檔案系統的資源 (即檔案和檔案系統的資訊)。 延伸閱讀: * [Linux 核心設計: 檔案系統概念及實作手法](https://hackmd.io/@sysprog/linux-file-system) ## 中央大廳層 中央大廳相當熱鬧,除了一群小企鵝,尚可見到小精靈和小狗: ![image](https://hackmd.io/_uploads/BkfszSJc6.png) 我們從右下側 (即靠近讀者的一側),以順時鐘方向,逐一介紹中央大廳的成員和其寓意。 ### 行程表 中央大廳最醒目的區域,就是一塊地毯上,眾多小企鵝在圍著桌子坐著,這區域是行程表 (process table)。 ![image](https://hackmd.io/_uploads/r1asfB15T.png) > 英語的「表格」和「桌子」是同一個字,漫畫藉由這樣的雙關,展現行程管理 左上角有個站立的小企鵝,是其他小企鵝的長輩,照顧著狀態不一的小企鵝,這個慈母企鵝 (也可以是祖母、曾祖母等身份) 表示 PID 為 1 的行程,即 [init](https://en.wikipedia.org/wiki/Init) 或 [systemd](https://en.wikipedia.org/wiki/Systemd),所有使用者層級的行程都由其產生 (藉由 [fork](https://man7.org/linux/man-pages/man2/fork.2.html) 或 [clone](https://man7.org/linux/man-pages/man2/clone.2.html) 系統呼叫)。示意如下圖: ![image](https://hackmd.io/_uploads/SJYpGHk96.png) 圍繞在桌子的小企鵝們處於打盹 (sleep)、發呆 (stop),也有跟慈母企鵝互動的活躍 (running) 等狀態,對應到 Linux 核心對於行程的狀態及生命週期規範: ![image](https://hackmd.io/_uploads/r1J0frJqp.png) 一旦慈母企鵝對著 PID 為 `171`、背對慈母的小企鵝說:「孩子,現在輪到你發言」,就相當於排程器 (scheduler) 挑選出下一個要執行的任務。 Daniel Stori 尚有一則漫畫,標題是 "[forked!](https://turnoff.us/geek/forked/)" ![image](https://hackmd.io/_uploads/BycM8Aaq6.png =80%x) [fork](https://man7.org/linux/man-pages/man2/fork.2.html) 系統呼叫不需要任何參數,也就是說,你沒辦法在建立一個新行程之前去設定這個新行程的任何參數,比如優先等級等。在呼叫 fork 之前什麼都沒有,然而在 fork 呼叫結束後就什麼都有。也就是說,新行程繼承親代行程的一切!那麼,**為何一切都繼承親代行程呢?** 因為懶!這可是 UNIX 共同發明人 Dennis Ritchie 自己說的話。 1964 年發展的 [Project Genie](https://en.wikipedia.org/wiki/Project_Genie) 分時多工系統是首個實作 fork 的作業系統,在 Unix 之前。Genie 的 fork 遠比 Unix 的 fork 靈活,而 Unix 的 fork 其實是對 Genie 作業系統裡頭 fork 的拙劣摹仿,也就是想照抄 Genie 分時多工系統的 fork,然而抄到一半覺得太麻煩,乾脆把親代行程複製一遍就好。換句話說,沒有參數的 fork 呼叫就是 Unix 一種臨時的方案,後者最終遺留許多問題。 Linux 核心是個類似 Unix 的系統核心,自然也繼承這歷史包袱,後來 POSIX 規範的 [posix_spawn](https://man7.org/linux/man-pages/man3/posix_spawn.3.html) 可說是對 fork 系統呼叫使用方式的修正。 Daniel Stori 另一則漫畫,標題是 "[brothers conflict (at linux kernel)](https://turnoff.us/geek/brothers-conflict/)" ![image](https://hackmd.io/_uploads/HkgeRZ6cp.png =90%x) Linux 發展之初是個以單一執行緒為導向的作業系統,儘管 1996 年出現 [LinuxThreads](https://en.wikipedia.org/wiki/LinuxThreads),得以支援多執行緒程式設計的介面,但真正針對多核處理器的多執行緒等 Linux 核心發展 10 年後才納入,也就是 [NPTL](https://en.wikipedia.org/wiki/Native_POSIX_Thread_Library)。在此之前,Linux 的多執行緒實作非常奇怪,仍然把行程當作最基本的執行單元,也就是說排程和上下文交換 (context switch) 等基本操作對象仍是行程。 UNIX 作業系統發展的前期,根本就沒有執行緒的概念。那時候行程就是一切,而行程的一切就是個獨享的地址空間。後來慢慢起變化: * 執行緒出現,多個執行緒共享同個地址空間; * 地址空間不再是一切,還包括很多其他不在主記憶體的硬體狀態上下文 (context); * 對於 Linux 核心的實作,不管是執行緒還是行程 (只有一個執行緒的行程),一切都是 `task_struct`。fork 發生之際,子行程複製的僅是呼叫執行緒的 `task_struct`。倘若這時操作同一個地址空間的其他 task_struct 持有 lock,即便呼叫 fork 的 `task_struct` 並不知道這件事 (要持有 lock 後才知),但這個事實還是會悄無聲息地傳給子行程。子行程如果這時候想去持有 lock,會發生死結! [brothers conflict (at linux kernel)](https://turnoff.us/geek/brothers-conflict/) 就展示前述的行程和執行緒在 Linux 核心的關係,特別彰顯於資源共享。 Daniel Stori 其他相關漫畫: * [zombie processes](https://turnoff.us/geek/zombie-processes/): 親代行程和它生成的子行程的運作方式是非同步,這意味著,當子行程執行結束後,會留下一些訊息需要親代行程藉由 [wait/waitpid](https://man7.org/linux/man-pages/man2/wait.2.html) 來回收系統資源。但若親代行程忙到沒空呼叫 wait/waitpid,那麼子行程就會變成殭屍行程。 * [the real reason to not use sigkill](https://turnoff.us/geek/dont-sigkill/), [adopt a good cause, don't sigkill](https://linux.cn/article-8771-1.html): 在 Linux 中,常藉由發送 [signal](https://man7.org/linux/man-pages/man7/signal.7.html) 以結束行程,通常用來幹掉行程的訊號包含 [SIGTERM](https://man7.org/linux/man-pages/man7/signal.7.html) 和 [SIGKILL](https://man7.org/linux/man-pages/man7/signal.7.html)。但若你希望行程得以善終,就別急著發送 SIGKILL,因為該 signal 不會被攔截,行程一旦收到,就會立刻退出,連收尾清理的機會都沒有 —— 尚且包括關閉執行緒 (漫畫中的小朋友) 等動作。更聰明的作法是發送 `SIGTERM`,這樣行程在收到後,可能有機會做些準備退出的動作。 延伸閱讀: * [Linux 核心設計: 不僅是個執行單元的 Process](https://hackmd.io/@sysprog/linux-process) * [Linux 核心設計: 不只挑選任務的排程器](https://hackmd.io/@sysprog/linux-scheduler) * [UNIX 作業系統 fork/exec 系統呼叫的前世今生](https://hackmd.io/@sysprog/unix-fork-exec) ### 記憶體管理 記憶體管理是 Linux 核心裡頭最複雜的部分,涉及到對計算機結構、slob/slab/slub 記憶體配置器、行程和執行檔樣貌、虛擬記憶體對應的例外處理、記憶體映射, UMA vs. NUMA 等等議題。 Daniel Stori 另一則漫畫,標題是 "[kernel economics](https://turnoff.us/geek/kernel-economics/)": ![image](https://hackmd.io/_uploads/rJnG3CTqp.png =80%x) 現代銀行與虛擬記憶體的運作驚人地相似:當你從 malloc() 獲得一個非 `NULL` (`NULL` 定義為 `(void *) 0`) 的指標時,依據 C 語言的風格,非 0 就為「真」,但別急著高興,因為當你真正開始使用這塊記憶體空間時,可能會面臨作業系統發出的記憶體不足 (out-of-memory; OOM) 警告 —— 就好比你拿到一張支票,到底能不能兌現,你要實際去銀行時方可確定。 為何有這樣的機制?Linux 這樣可用在伺服器或者高性能運算的作業系統,往往具備 overcommit 的特徵,後者是說當配置已被使用的位址,其實是預先支出,只要使用者不會立即配置、立即存取該記憶體空間,等待之前使用該記憶體位址的資料,只要及時釋放空間,仍可順利使用該位址,這樣就可讓同一時間有更多的應用程式得以順利執行。但也因為 overcommit 的存在,OOM 變成影響系統運作的不定期炸彈。Linux 核心提供內建的 OOM killer,顧名思義就是由 Linux 核心在 OOM 發生時,依據某些預先寫好的條件,主動去釋放特定的行程。 延伸閱讀: * [Linux 核心設計: 記憶體管理](https://hackmd.io/@sysprog/linux-memory) ### 資訊安全 Daniel Stori 另一則漫畫,標題是 "[intel bug](https://turnoff.us/geek/intel-bug/)" ![image](https://hackmd.io/_uploads/Bygwg1R5p.png =80%x) 當我們談論資訊安全時,大部分人立刻想到的是電腦病毒和防毒軟體等軟體相關術語。然而,近年來,硬體安全問題也在電子產業中頻繁被提起。2018 年,Intel 處理器爆出嚴重的硬體漏洞,例如 Meltdown 和 Spectre,這些漏洞能讓攻擊者任意讀取記憶體資料,從而引起廣泛關注,Linux 核心儘管有對應的緩解之計,不過對於性能有顯著的衝擊,上述的漫畫就是諷刺這件事,誇張的說 Intel Core i7 產品一旦使用針對硬體的安全修正後,就變成緩慢的 Intel 80386,這並非事實,但資訊安全和系統效能的確是今日 Linux 核心發展的拉鋸。 1990 年代後期到 21 世紀初,計算機結構創新開始放緩,帶來二個挑戰: * 效能提升減緩:單核處理器的性能每年提升率已下降到 3% * 安全性問題:之前一直以軟體和系統來提升安全性,而忽略對硬體安全性的把控,由於計算機結構的設計漏洞,Spectre 和 Meltdown 這類弱點於是有可乘之機; ### 看門狗 行程表兩側各有一隻小狗,它們監控著小企鵝的狀態: ![image](https://hackmd.io/_uploads/B1URfr1q6.png) 當小企鵝不聽話時,它們就會吠叫,不見得是 Linux 行程出錯,也可能因為裝置驅動程式或核心內部狀態陷入無法復原,這也是 "watchdog" 一詞的引申意義。實務上,Linux 伺服器系統在出現致命錯誤,需要遠端進行重新啟動,就可搭配 watchdog,藉由後者監控系統資料,判斷是否在系統出現異常時,自動重新啟動系統。 延伸閱讀: * [Linux Watchdog Support](https://www.kernel.org/doc/html/latest/watchdog/) ### httpd 行程 大廳對外的門戶,由一隻胸前標註 `1341` 的小企鵝所看守,它頭上插著一只羽毛,門上寫着 `80`,說明這個 PID 爲 `1341` 的 Linux 行程負責接待埠號 (port) `80`,後者也就是 HTTP 常見的連接埠。 ![image](https://hackmd.io/_uploads/ByPJ7HJca.png) > [中文詞彙地區差異比較——#16「端口」與「埠」](https://byvoid.com/zht/blog/region-phrases-comparison-port/) 小企鵝頭上的一只羽毛大有來歷,它是著名的 [Apache HTTP 伺服器](https://httpd.apache.org/) 的識別圖樣: ![image](https://hackmd.io/_uploads/rkegmS1cp.png) 網頁伺服器 ([web server](https://en.wikipedia.org/wiki/Web_server)) 也稱 HTTP server 或 HTTP daemon,可簡稱 `httpd`,後者的 "[daemon](https://en.wikipedia.org/wiki/Daemon_(computing))" 原為「惡魔」之意,在 UNIX 的世界中引申爲常駐程式或背景服務。 Daniel Stori 另一則漫畫,標題是 "[life in a web server](https://turnoff.us/geek/life-in-a-web-server/)" 解釋網頁伺服器運作原理。 ![image](https://hackmd.io/_uploads/SJouVyCca.png =80%x) 這漫畫背後展現的是事件驅動 (event-driven) 概念,沒有明確的科學定義,不過要了解 event-driven 的行為不難,可參考〈[如何向你阿嬤解釋 "Event-Driven" Web Servers](https://daverecycles.tumblr.com/post/3104767110/explain-event-driven-web-servers-to-your-grandma)〉,考慮以下: * 傳統網頁伺服器 - 想像有間餐廳,只雇用一個店員,當有客戶打電話進來訂餐時,店員收到訂單後不會掛斷電話,直到餐點做好後,店員通知客戶可以來拿後,再掛斷電話。 - 本模式很明顯的缺點是,在服務某客戶期間,無法接洽其他客戶,直接影響著用戶體驗 (latency) 與單位時間的服務量 (throughput)。 * 事件驅動的網頁伺服器 - 另一間餐廳同樣只雇用一個店員,當有客戶打電話進來訂餐時,店員收到訂單後會馬上掛斷電話,然後等到餐點製作完畢,再打電話通知客戶可以來拿取。期間因為電話已掛斷,所以仍可持續收到更多的訂單。當然可請更多員工 (worker thread in thread pool) 在廚房烤餐點來增加單位時間的服務量 (throughput)。 - 不過一旦員工數量持續增長,餐廳的容量反而是限制 (capacity)。 包含 Apache 在內的網頁伺服器大多採取事件驅動的設計。 延伸閱讀: * [事件驅動伺服器:原理和實例](https://hackmd.io/@sysprog/event-driven-server) Linux 核心在 2.4 版的年代,當時 Linux 的效能不夠好,且無法有效利用多處理器的優勢、執行緒的實作仍很拙劣,但 Linux 卻恰好滿足 Intel x86 架構和個人電腦物美價廉的特性,廣泛採納為網際網路服務的基礎,因此當時 Linux 開發者有鑑於 [Apache 伺服器](https://httpd.apache.org/)多半在 Linux 上運作,網頁伺服器又是如此普遍且重要,就在 Linux 核心提供名為 `khttpd` 的網頁伺服器 (in-kernel httpd) 作為加速,後來演化為 [TUX](https://en.wikipedia.org/wiki/TUX_web_server) —— 用 Linux 的吉祥物來命名 in-kernel web server。 不過後來 Linux 核心開發者就不維護 `khttpd` 或 `TUX`,而是提供 [sendfile](https://man7.org/linux/man-pages/man2/sendfile.2.html), [epoll](https://man7.org/linux/man-pages/man7/epoll.7.html), [splice](https://man7.org/linux/man-pages/man2/splice.2.html) 等系統呼叫,搭配 scalability 更好的 CPU 排程器 (CFS),因為他們從多年的實踐,總結這樣的策略:「沒必要透過特化需求去克服局部的效能瓶頸」。 延伸閱讀: * [Linux 核心設計: 發展動態回顧](https://hackmd.io/@sysprog/linux-dev-review) * [Linux 核心設計: 針對事件驅動的 I/O 模型演化](https://hackmd.io/@sysprog/linux-io-model/) * [Linux 核心設計: Scalability 議題](https://hackmd.io/@sysprog/linux-scalability) * [Effective System Call Aggregation (ESCA)](https://eecheng87.github.io/ESCA/) ### cron 任務 在這一層中,有一個身上寫着 `217` 的小企鵝,他正滿頭大汗地反覆查看自己的手錶,深怕沒趕上預定的時間安排: ![image](https://hackmd.io/_uploads/SJql7HJc6.png) 這隻小企鵝就是 [cron](https://en.wikipedia.org/wiki/Cron),作用是例行性工作排程,按時執行週期性任務,或判斷是否要執行某個工作。 延伸閱讀: * [例行性工作排程 (crontab)](http://linux.vbird.org/linux_basic/0430cron.php) ### 管線 有兩個小企鵝扛着管線 ([PipeLine](https://en.wikipedia.org/wiki/Pipeline_(Unix)),可簡稱為 [pipe](https://man7.org/linux/man-pages/man7/pipe.7.html)) 在行走,一隻小企鵝可以把自己手上的東西通過這個管線,傳遞給後面的小企鵝。 ![image](https://hackmd.io/_uploads/r1Q-mrkca.png) [pipe](https://en.wikipedia.org/wiki/Pipeline_(Unix)) 是 UNIX 的重要發明,慣用的 `|` 符號,就像一根管子,將左右兩邊命令的輸出和輸入連接起來。左側命令的輸出,會當作右側命令的輸入。在 pipe 機制出現之前,使用者只能將一個命令或程式執行的結果,暫時保存於檔案中,再執行另一個程式,將暫存檔內的資料,提供給第二個指令作為它的輸入,而 pipe 機制在程式設計上具有高度的彈性,也是 UNIX 獲得廣泛採納的重要因素:一個又一個 UNIX 工具、大小規模不一的程式,以及使用者撰寫的腳本 (script) 程式,以接力方式串接起來,共同完成任務,就像用不同孔徑的篩子,將原始資料逐步轉化為最終的形式。 ![image](https://hackmd.io/_uploads/SJ5W7B1c6.png) > 出處: [Pipes, Forks, & Dups: Understanding Command Execution and Input/Output Data Flow](http://www.rozmichelle.com/pipes-forks-dups/) Linux 核心為了實作 pipe,內部實作 pipe buffer,隨後甚至出現 [splice](https://man7.org/linux/man-pages/man2/splice.2.html) 系統呼叫。 延伸閱讀: * [Mastering UNIX pipes, Part 1](https://www.moritz.systems/blog/mastering-unix-pipes-part-1/) * [Mastering UNIX pipes, Part 2](https://www.moritz.systems/blog/mastering-unix-pipes-part-2/) ### 無人看守的 FTP 行程 除了上述的埠號 `80`,大廳另有個門戶,上方寫 `21`,但實在年久失修,連門牌都快脫落: ![image](https://hackmd.io/_uploads/ryGz7S15T.png) 這個埠號 `21` 就是 [File Transfer Protocol](https://en.wikipedia.org/wiki/File_Transfer_Protocol),簡稱 FTP,一度廣泛採用,但現在大部分人已改用 SSH 和 [SSH File Transfer Protocol](https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) (簡稱 `sftp`) 或 [rsync](https://en.wikipedia.org/wiki/Rsync)。 近期 Google Chrome 網頁瀏覽器[移除對 FTP 的支援](https://chromestatus.com/feature/6246151319715840): > The current FTP implementation in Google Chrome has no support for encrypted connections (FTPS), nor proxies. Usage of FTP in the browser is sufficiently low that it is no longer viable to invest in improving the existing FTP client. In addition more capable FTP clients are available on all affected platforms. ### 戒備森嚴的 SSH 伺服器 大廳最後一道門戶,由一位配戴墨鏡和警徽的冷酷企鵝守護著。門上標注 `22`,表示埠號 `22` 的 [SSH 服務](https://en.wikipedia.org/wiki/Secure_Shell_Protocol)。 ![image](https://hackmd.io/_uploads/rk5fQrJc6.png) 這隻冷酷企鵝顯然比其他的企鵝嚴肅,臉上彷彿寫著「生人勿進」四字,因為 SSH 通訊協定背後涉及身份識別、加密,和遠端登入等操作,伺服器需要仔細盤查和核對。 Daniel Stori 另一則漫畫,標題是 "linus torvald's house",除了展示 Linux 系統常見以 SSH 作為門戶,也暗指沒有窗戶 (windows,雙關語)。 ![image](https://hackmd.io/_uploads/H1Ze_MicT.png) > 出處: [turnoff.us: linus torvald's house](https://turnoff.us/geek/linus-torvalds-house/) 延伸閱讀: * [遠端連線伺服器 SSH](https://linux.vbird.org/linux_server/centos6/0310telnetssh.php) ### [Wine](https://www.winehq.org/) 行程 這位端著紅酒,略帶醉意、胸前標注 PID `411` 就是 [Wine](https://www.winehq.org/) 行程: ![image](https://hackmd.io/_uploads/H1lmXmHkcT.png) 小企鵝喝紅酒,微醺地走著,好似自己是 Microsoft Windows 並提供執行應用程式所需的 API 相容層。[Wine](https://www.winehq.org/) 這項開放原始碼專案最初以 "Wine Is Not an Emulator" 的遞迴式縮寫命名,致敬 [GNU](https://www.gnu.org/) 為 GNU's Not Unix,英文的 "wine" 是紅酒的意思,[Wine](https://www.winehq.org/) 專案的圖樣正是紅酒: ![image](https://hackmd.io/_uploads/r1YmQHJ9T.png) 有了 Wine,我們即可在 Linux 執行原本針對 Microsoft Windows 的應用程式,該專案背後的推手是 [CodeWeavers](https://www.codeweavers.com/) 公司,長期貢獻程式碼到 [Wine](https://www.winehq.org/) 專案,近期另一間以開放原始碼技術為訴求的 [Collabora](https://www.collabora.com/) 公司也強化 [Wine](https://www.winehq.org/) 的圖形處理,這二間公司以 WINE 為基礎,合作開發 [Proton](https://github.com/ValveSoftware/Proton),允許 MS-Windows 遊戲在 Linux 作業系統上順暢執行。 Linux 核心發布於 1991 年,隔年 XFree86 專案支援 Linux,使得 Linux 核心具備傳統 UNIX 一樣的 X Window System,到了 1993 年,極具野心的 WINE 建立,希望在 Linux 上模擬 Win32/Win16 API,以便在 Linux 上面執行 Windows 應用程式。1994 年,Linus Torvalds 出席 [DECUS](https://en.wikipedia.org/wiki/DECUS) 會議 (Digital Equipment Computer Users Society),當時 24 歲的他發表二場演講,介紹 Linux 及其實作,整個大會約有 1.9 萬人,不過僅有 40 人前來聽他的演講 (後來 Linus 就不用自己製作投影片,純口述還是上千人捧場),演講尾聲,Linus Torvalds 提到他需要 WINE,以便執行 MS-PowerPoint 和 MS-Word。 延伸閱讀: * [Linus Torvalds at DECUS '94](https://linuxjournal.rubdos.be/ljarchive/LJ/004/2791.html) * [The lost talks from Linus Torvalds at DECUS'94](https://github.com/scateu/some_podcast_transcriptions/tree/main/interviews/Torvalds_1994) > [Jon Maddog Hall's note](https://www.facebook.com/maddoghall/posts/pfbid0c9vawf8hyvc4sHizqp46oNEQzPB2mXCSKTJwjNZA3Y4QsMnoYEfCEWsrquwco8Nkl) Daniel Stori 另一則漫畫 [the war for port 80 - epilogue](https://turnoff.us/geek/apache-vs-nginx-epilogue/) ![image](https://hackmd.io/_uploads/SycBNCa5p.png) 說 Nginx 和 Apache 這二套流行的網頁伺服器競爭著 HTTP 預設的 80 埠號時,Linux 系統藉由 WINE 執行 Microsoft 公司開發的 [IIS](https://en.wikipedia.org/wiki/Internet_Information_Services) 網頁伺服器。 值得留意的是,為了更好地執行 Wine,Linux 核心陸續加入新的修改,可參見以下: * [Linux Kernel: Syscall User Dispatch](https://www.kernel.org/doc/html/latest/admin-guide/syscall-user-dispatch.html) * [FUTEX2 Spun Up A Fifth Time For This Linux Interface To Help Windows Games](https://www.phoronix.com/scan.php?page=news_item&px=FUTEX2-v5) * [Windows NT Sync Driver Proposed For The Linux Kernel - Better Wine Performance](https://www.phoronix.com/news/Windows-NT-Sync-RFC-Linux) ### GNOME 這位活蹦亂跳的小精靈是誰? ![image](https://hackmd.io/_uploads/S1lEmBy9a.png) 是大名鼎鼎的 [GNOME 桌面環境](https://www.gnome.org/),推出時間稍晚於 [KDE 桌面環境](https://kde.org/)。既然定位是桌面環境,就不會只有一隻程式,因此對應到 Linux 的行程來說,[GNOME 桌面環境](https://www.gnome.org/) 啟動後,會建立一系列 Linux 行程且相互溝通。 [GNOME 桌面環境](https://www.gnome.org/) 的吉祥物是花園地精 (Garden Gnome),在歐洲相當普遍,誕生於 16 世紀的義大利,陸續由各地手工藝精湛的師傅們賦予他們多種樣貌,於是電影和家具店中都可其身影。GNOME 最初是 GNU Network Object Model Environment 的簡稱,不過這個 Network Object Model 可能跟許多人想的不同,這個 "network" 是指 GNOME 專案創立初期使用 [Common Object Request Broker Architecture](https://en.wikipedia.org/wiki/Common_Object_Request_Broker_Architecture) (CORBA) 這個分散式運算架構並包裝為 [Bonobo](https://en.wikipedia.org/wiki/Bonobo_(GNOME)),後來開發者體會到,在桌面環境使用 CORBA 實在是「殺雞用牛刀」,也比照 KDE 專案,改用 [D-Bus](https://www.freedesktop.org/wiki/Software/dbus/) 來處理個元件乃至應用程式開發框架之間的通訊議題。 ## 最上方的介面 接著來看樓中樓上方區域,也是最接近使用者的一層。 ![image](https://hackmd.io/_uploads/HkdNXBkqa.png) 兩隻小企鵝忙碌地工作:一隻企鵝在控制台前操作,另一隻仔細端詳程式輸出結果,我們可見 `tty` 字樣標註在個別螢幕上,例如 `tty4` 上面輸入 `fre` 字樣 (可能是準備執行 [free](https://man7.org/linux/man-pages/man1/free.1.html) 工具程式或內建命令)、`tty3` 有 `awk` 字樣 (準備執行 [awk](https://man7.org/linux/man-pages/man1/awk.1p.html) 腳本)、`tty2` 是執行 `ls` 命令的輸出 (可見 `/dev`, `/etc`, `/usr`, `/bin`, `/sbin` 等目錄),至於 `tty7` 就有意思了,是視窗圖形介面,由 [X Window System](https://www.x.org/) 提供基礎建設,可能執行上述提到的 [GNOME 桌面環境](https://www.gnome.org/)。 > 延伸閱讀: [第二十三章、X Window 設定介紹](https://linux.vbird.org/linux_basic/centos7/0590xwindow.php) 至於 `tty` 到底是什麼,要從一段故事談起。 ![image](https://hackmd.io/_uploads/ryGrmSk5p.png) > ticker tape, 1918 1869,股票自動報價機 ([stock ticker machine](https://en.wikipedia.org/wiki/Ticker_tape)) 問世,其組成包含以下: * 用於長距離即時傳遞股票價格的電子/機械設備 * 打字機 (typewriter) * 一對長電纜 * 一個報價用的磁帶印表機 (tape printer) 後來演變為速度更快、以 ASCII 編碼為基礎的的電傳打字機 ([teletyper](https://en.wikipedia.org/wiki/Teleprinter)),後者甚至可用電纜串接,用來傳遞商業電報,但彼時尚未有電子計算機。 第二次世界大戰刺激電子計算機的發展,在 1940 年代末期,John von Neumann 博士和他所屬的洛斯阿拉莫斯國家實驗室深入運用 [ENIAC](https://en.wikipedia.org/wiki/ENIAC) 電子計算機,計算氫彈相關資料,輸出資料量高達 100 萬張卡片。 後來電腦融入 [CTSS](https://en.wikipedia.org/wiki/Compatible_Time-Sharing_System) 帶來的分時多工機制,得以落實多任務 (multitasking),且功能和運算速度都持續提升,電腦得以有效地和操作者互動,人們就將電傳打字機用作電腦的輸入和輸出設備,因為這些設備在市場上容易取得。 ![image](https://hackmd.io/_uploads/r1TBQSJ9p.png) 但此時面臨的問題是:市場上已有不少的電傳打字機廠牌,所有機種之間都些微差異,因此就需要某種中間層來隱蔽 (abstract) 這些落差,於是當人們在電腦前說電傳打字機時,其實是 `tty` (電傳打字機的簡寫) 和低階操作的統稱,例如 word 長度, baud rate, flow control, parity, line editing 等功能所用的控制碼等等。 > Microsoft 共同創辦人 Paul Allen 及 Bill Gates 展示 teletype 的使用 > ![](https://hackmd.io/_uploads/S1rmuKnsj.png) > [出處](https://twitter.com/BillGates/status/1145696067285114881) 儘管電傳打字機的實體早已消聲匿跡,但 `tty` 的影響卻從 20 世紀中葉持續影響資訊科技產業,我們在 UNIX 和其後繼者 (如 Linux) 內部可見 `tty`,上述的控制碼依然存在,這也是為何有 "[terminal emulator](https://en.wikipedia.org/wiki/Terminal_emulator)" 一詞,因為包含 Linux 這樣的 21 世紀作業系統用軟體去「模擬」著 20 世紀的電傳打字機 (`tty`) 硬體和支援多種控制碼,以做到個別「模擬」出來的終端機 (terminal) 之間可以互通。 換言之,`tty` 對應的終端機是作業系統對外的操作和通訊的機制,我們熟悉的標準輸出和輸入 (即 `stdout`, `stdin`) 就可在指定的 `tty` 裝置上處理。漫畫中二隻忙碌的企鵝,正是藉由 `tty` 來處理輸入和輸出的動作。但 `tty` 並非作業系統對外溝通的唯一機制,我們可運用網路 (networking; 不必是網際網路 [internet]) 的連接埠,事先約定通訊協定和方法,進行通訊和提供服務。 延伸閱讀: * [你所不知道的 C 語言: Stream I/O, EOF 和例外處理](https://hackmd.io/@sysprog/c-stream-io) * [The TTY demystified](https://www.linusakesson.net/programming/tty/) * [TTY 到底是什麼?](https://www.kawabangga.com/posts/4515) ## Linux 究竟包含哪些部分? 當我們重新檢視 [inside the linux kernel](https://turnoff.us/geek/inside-the-linux-kernel/) 漫畫,不難發現其實只有一部分是真正存在於 Linux 核心,例如 process table, file system, scheduler, 和 tty 底層的實作,至於漫畫中大廳出現的大部分角色則隸屬於使用者層級 (user-level,或 userland)。