當前位置: 華文問答 > 科學

如何從零開始自制作業系統?

2015-01-20科學

MIT 6.828 ,YYDS!

國內不少大學,老師講課太水,就是讓你背概念。 但是作業系統這門課 很!重!要!

在這說下我是怎麽學好這門課的吧。

當時看了不少網課,然後自己跟著教程」抄了「一個 mini os。

學習作業系統一定不要去死看書,最好跟著那種有配套實驗完成一個os的課程或者書。

就像這種:

學習電腦一定不要想著速成,要下苦功夫,去啃那些經典書和源碼,然後自己動手寫,我大學整理了一套電腦必讀的經典書籍,對於CS學習的同學幫助非常大,且十分系統,現在免費分享給大家:

比如我當時看完了網易雲課堂上李治軍老師的課程,他的課程最大的特點就是理論結合實踐,比如講執行緒切換,那就會拿出linux 0.11的程式碼帶我們一起去看具體的實作,棧、上下文、寄存器是如何切換的。

接下來給大家講講我推薦的作業系統學習方法吧:

來源: 個人公眾號「編程指北」,推薦關註! 原文:編程指北--電腦科班學習 OS 的正確姿勢!

實際上作業系統發展到今天,已經非常復雜了,像 Windows、Linux 任意一個都是幾千萬行程式碼級別,想靠個人完全搞懂,幾乎是不可能的了。

所以需要先明確一下我們學習的目的,不同的學習目的,適用不同的方法,這裏我僅僅列一下作為一名開發人員,我們掌握 OS 的幾種目標:

第一種:

知曉 OS 基本概念: 看線上課程原理部份的影片或者看【現代作業系統】之類的書,可大致知道OS的概念;

第二種:

理解OS基本原理: 在1的基礎上,完成與 OS 相關的課程練習題,可進一步理解 OS 基本原理,練習題可以參考學堂線上清華OS課程的練習題:

第三種:

掌握 OS 部份核心功能實作(細節):在 2 的基礎上,能夠透過編程完成類似 xv6 的幾個 lab ,

比如 xv6 就會涉及以下模組:

  • Booting a PC
  • Memory Management
  • Multitasking
  • File system, Spawn and Shell
  • Network Driver
  • 每個模組程式碼量都不會很多,但是麻雀雖小,五臟俱全,透過自己動手實作 thread、spinlock、semaphore 這些東西,會讓你理解更加深刻。

    當然,在往上走就是去研究最新 Linux Kernel,研究一些子模組了,有些還需要閱讀最新的 System 領體論文。

    最新的 Linux Kernel 裏有很多新的演算法、研究結果不斷的加入。

    當然,這就超出了我所能掌握的範疇了哈哈。

    不過說實話,如果你還在校大二大三,我真的墻裂建議你去做一些國外的電腦 lab,比如OS、Network。

    等到畢業了,幾乎就不太可能從頭開始系統學習那些基礎知識了,除非你能自己閉關兩三年,啥也不做,待在一個地方專心修煉。

    好好珍惜在學校大把的空閑時間,做一些讓在專業上讓自己受益一生的事情。

    這裏我可以列舉幾個,國內不少喜歡 System 的同學都會去跟 MIT、CMU、UCB 這些電腦名校的課程。

    比如 MIT 的 6.824 Distributed System 6.830 Database Systems MIT 6.828 Operating System Engineering .....

    小北也搜集了很多作業系統硬核的實驗和lab,大家可以看下這篇文章,結合lab學習一定會事半功倍:

    xv6

    6.828 就是今天要介紹的主角:

    MIT6.828: Operating System Engineering

    官網主頁:https:// pdos.csail.mit.edu/6.82 8/2020/index.html

    在官網,包含了Schedule、Labs、xv6-book 等等。

    尤其是 xv6-lab 包含了作業系統中最為核心的模組:

    每個模組都搭好了框架,留下最為核心的部份給我們去實作,你可以把這個看做一種「完形填空」:

  • System Call、Page tables
  • Traps
  • Lazy allocation、Copy On-Write
  • Multithreading、Lock
  • File System、mmpa
  • network driver
  • 如果想看影片的話可以去 Youtube 或者 B站:

    MIT 6.828: Operating System Engineering : https://www. bilibili.com/video/BV1p x411E7ST

    ucore

    如果你想找一個國內的類似 xv6 的 lab,那麽這裏推薦清華大學 ucore OS。

    它其實也是起源於MIT CSAIL PDOS課題組開發的 xv6 & jos、哈佛大學開發的 OS161教學作業系統、以及Linux-2.4 內核。

    然後清華的老師在這個基礎上,增加、調整了一些程式碼,為清華大學 OS 課程設計的一個lab。

    另外,這個課程的很多資料、文件都是中文的,還有清華老師的配套影片課程。

    清華大學-作業系統:https://www. xuetangx.com/course/THU 08091000267/5883104

    順便推薦幾本經典的書籍吧:

    書名(英文):Operating Systems : Design and Implementation (3rd Edition) 書名(中文):作業系統:設計及實作 (第三版) 原作者:Andrew S. Tanenbaum / Albert S. Woodhull 轉譯者:王鵬、尤晉元、朱鵬、敖青雲 Operating System (作業系統) 書名(英文):Operating System Concepts (7th Edition) 書名(中文):作業系統概念 (第七版) 原作者:Abraham Silberschatz / Peter Baer Galvin / Greg Gagne

    另外還有諸如【現代作業系統】、【Operating Systems: Three Easy Pieces】之類的。

    尤其是 【Operating Systems: Three Easy Pieces】,閱讀體驗比較好,討論問題由淺入深。

    而書名也是很有意思,Three Easy Piece是為了致敬費曼的關於物理學的書籍:【Six Easy Pieces: Essentials Of Physics Explained By Its Most Brilliant Teacher】。

    用作者的話說,作業系統只有物理學一半難,那就叫 【Three Easy Pieces】好了。

    Three 也是指代本書三個部份:

  • 虛擬化( Virtualization
  • 並行( Concurrency
  • 持久化( Persistence
  • 作業系統這門課,易學難精,但是掌握到日常編程和面試夠用還是比較容易的。

    那麽畢業生或者說你去準備校招面試應該達到怎樣的水平:

  • OS 四大模組的理論知識: 行程與執行緒管理、記憶體管理、IO與檔案系統、器材管理
  • 了解 Linux 內核部份實作原理,如記憶體管理、行程管理、虛擬檔案系統等
  • 了解和熟悉常用的系統呼叫已經 System API
  • 其中記憶體、行程、IO 是重點,這幾塊也是和編程關系最密切的,這裏推薦先挑本偏理論的書看看,了解作業系統的全貌:

  • 【現代作業系統】
  • 【作業系統—精髓與設計原理】
  • 不必全看,兩者任選一本都不錯,我自己是仔細看了第二本,因為是我們教材,同時挑著看了現代作業系統部份章節。

    作業系統包含的知識

    這部份看完你應該對下面這些話題有一個清晰認知了:

  • 作業系統由哪些構成
  • 行程的狀態、切換、排程
  • 行程間通訊方式(共享記憶體、管道、訊息)
  • 行程和執行緒的區別
  • 執行緒的實作方式(一對一、多對一等)
  • 互斥與同步(信號標、管程、鎖)
  • 死結檢測與避免
  • 並行經典的問題:讀者寫者、哲學家就餐問題
  • 為什麽需要虛擬記憶體,MMU 具體如何做地址轉換的
  • 記憶體為什麽分段、分頁
  • 頁面置換演算法
  • 檔案系統是如何組織的
  • 虛擬檔案系統(VFS)是如何抽象的
  • ...
  • 但是這還不夠,看完偏理論的書,當面試官問「行程和執行緒的區別」時。

    大概只能回答出「行程是資源分配的最小單位,執行緒是CPU排程的最小單位,balabala...」這樣正確卻普通的答案。

    但是如果你了解 Linux 內核的實作,就可以實際出發,講講 Linux 中行程和執行緒是如何建立的,區別在哪裏。

    比如在 Linux 中行程和執行緒實際上都是用一個結構體 task_struct來表示一個執行任務的實體。行程建立呼叫fork 系統呼叫,而執行緒建立則是 pthread_create 方法,但是這兩個方法最終都會呼叫到 do_fork 來做具體的建立操作 ,區別就在於傳入的參數不同。

    深究下去,你會發現 Linux 實作執行緒的方式簡直太巧妙了,實際上根本沒有 執行緒 ,它建立的就是行程,只不過透過參數指定多個行程之間共享某些資源(如虛擬記憶體、頁表、檔描述符等),函數呼叫棧、寄存器等執行緒私有數據則獨立。

    這樣是不是非常符合理論書上的定義:同一行程內的多個執行緒共享該行程的資源,但執行緒並不擁有資源,只是使用他們。

    這也算符合 Unix 的哲學了— KISS(Keep It Simple, Stupid)。

    但是在其它提供了專門執行緒支持的系統中,則會在行程控制表(PCB)中增加一個包含指向該行程所有執行緒的指標,然後再每個執行緒中再去包含自己獨占的資源。

    這算是非常正統的實作方式了,比如 Windows 就是這樣幹的。

    但是相比之下 Linux 就顯得取巧很多,也很簡潔。

    對於行程、執行緒這塊你還可以把 fork、vfork、clone 、pthread_create 這些模組關系徹底搞清楚,對你理解 Linux 下的行程實作有非常大的幫助。

    說了這麽多,就是想強調一下理論聯系實際的重要性。

    特別是作業系統,最好的實踐就是看下 Linux 內核是怎麽實作的,當然不是叫你直接去啃 Linux 源碼,那不是一般人能掌握的。

    最好的方式是看書,書的脈絡給你理得很清晰。

    書籍推薦:

  • 【Linux內核設計與實作】
  • 這本書恰到好處,即講清楚了內核實作的要點,又不會通篇源碼。

    這本書重點關註「第 3 章行程管理」、「第 5 章系統呼叫」、「第12章記憶體管理」、「第13章虛擬檔案系統」、「第 15 章行程地址空間」

    這些章節屬於作業系統核心部份,其它如中斷處理、塊 IO、器材管理根據你自己興趣選擇看下就可以了。

    基本上做到這裏,作業系統就沒什麽大問題了。

    小北也搜集了很多作業系統硬核的實驗和lab,大家可以去這篇文章下載,結合lab學習一定會事半功倍:

    自制OS

    另外,如果你還想自己寫一個(模仿) mini os,那麽你需要一些前置依賴知識,否則估計會被很多硬件、組譯知識勸退:

  • 築基內功 -- 需要學習電腦原理、C語言(需要熟練運用)、數據結構課程
  • 工欲善其事,必先利其器,掌握以下Linux 下常用命令列:
  • pwd、cd、find等,1-2 款趁手的編輯器,推薦掌握 vim 的基本操作 gcc、gdb、ld、make等編譯構建鏈、objdump、nm、readif、dd 等 ELF 檔分析、燒錄工具。

    這裏只推薦一本我看過的書【作業系統真象還原】,作者實在太好了,所有需要前置依賴的部份他都會簡單的寫個教程,照著這本書就能擼一個屬於自己的 os。

    另外,在這裏也送大家一本幫助我拿到BAT 等一線大廠 offer 的演算法筆記,是一位阿裏大神寫的,對於演算法薄弱或者需要提高的同學都十分受用,演算法一定是電腦學習的重中之重:

    覺得不錯的話,記得幫我 @編程指北 點個贊喲,祝大家新年快樂!