日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

xv6中文文档

發布時間:2023/12/9 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 xv6中文文档 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

操作系統的工作是

  • 將計算機的資源在多個程序間共享,并且給程序提供一系列比硬件本身更有用的服務。

  • 管理并抽象底層硬件,舉例來說,一個文字處理軟件(比如 word)不用去關心自己使用的是何種硬盤。

  • 多路復用硬件,使得多個程序可以(至少看起來是)同時運行的。(4)最后,給程序間提供一種受控的交互方式,使得程序之間可以共享數據、共同工作。

  • 操作系統通過接口向用戶程序提供服務。設計一個好的接口實際上是很難的。一方面我們希望接口設計得簡單和精準,使其
    易于正確地實現;另一方面,我們可能忍不住想為應用提供一些更加復雜的功能。解決這種矛盾的辦法是讓接口的設計依賴
    于少量的機制 (mechanism),而通過這些機制的組合提供強大、通用的功能。
    本書通過 xv6 操作系統來闡述操作系統的概念,它提供 Unix 操作系統中的基本接口(由 Ken Thompson 和 Dennis Ritchie
    引入),同時模仿 Unix 的內部設計。Unix 里機制結合良好的窄接口提供了令人吃驚的通用性。這樣的接口設計非常成功,
    使得包括 BSD,Linux,Mac OS X,Solaris (甚至 Microsoft Windows 在某種程度上)都有類似 Unix 的接口。理解 xv6 是
    理解這些操作系統的一個良好起點

    如圖0-1所示,xv6 使用了傳統的內核概念 - 一個向其他運行中程序提供服務的特殊程序。每一個運行中程序(稱之為進程)都擁有包含指令、數據、棧的內存空間。指令實現了程序的運算,數據是用于運算過程的變量,棧管理了程序的過程調用。
    進程通過系統調用使用內核服務。系統調用會進入內核,讓內核執行服務然后返回。所以進程總是在用戶空間和內核空間之間交替運行。
    內核使用了 CPU 的硬件保護機制來保證用戶進程只能訪問自己的內存空間。內核擁有實現保護機制所需的硬件權限
    (hardware privileges),而用戶程序沒有這些權限。當一個用戶程序進行一次系統調用時,硬件會提升特權級并且開始執行一
    些內核中預定義的功能。
    內核提供的一系列系統調用就是用戶程序可見的操作系統接口,xv6 內核提供了 Unix 傳統系統調用的一部分,它們是:

    這一章剩下的部分將說明 xv6 系統服務的概貌 —— 進程,內存,文件描述符,管道和文件系統,為了描述他們,我們給出
    了代碼和一些討論。這些系統調用在 shell 上的應用闡述了他們的設計是多么獨具匠心。
    shell 是一個普通的程序,它接受用戶輸入的命令并且執行它們,它也是傳統 Unix 系統中最基本的用戶界面。shell 作為一個
    普通程序,而不是內核的一部分,充分說明了系統調用接口的強大:shell 并不是一個特別的用戶程序。這也意味著 shell 是
    很容易被替代的,實際上這導致了現代 Unix 系統有著各種各樣的 shell,每一個都有著自己的用戶界面和腳本特性。xv6
    shell 本質上是一個 Unix Bourne shell 的簡單實現。它的實現在第 7850 行。
    一個 xv6 進程由兩部分組成,一部分是用戶內存空間(指令,數據,棧),另一部分是僅對內核可見的進程狀態。xv6 提供
    了分時特性:它在可用 CPU 之間不斷切換,決定哪一個等待中的進程被執行。當一個進程不在執行時,xv6 保存它的 CPU
    寄存器,當他們再次被執行時恢復這些寄存器的值。內核將每個進程和一個 pid (process identifier) 關聯起來。
    一個進程可以通過系統調用 fork 來創建一個新的進程。 fork 創建的新進程被稱為子進程,子進程的內存內容同創建它的
    進程(父進程)一樣。 fork 函數在父進程、子進程中都返回(一次調用兩次返回)。對于父進程它返回子進程的 pid,對于
    子進程它返回 0。考慮下面這段代碼:

    int pid; pid = fork(); if(pid > 0){printf("parent: child=%d\n", pid);pid = wait();printf("child %d is done\n", pid); } else if(pid == 0){printf("child: exiting\n");exit(); } else {printf("fork error\n"); }

    系統調用 exit 會導致調用它的進程停止運行,并且釋放諸如內存和打開文件在內的資源。系統調用 wait 會返回一個當前進程已退出的子進程,如果沒有子進程退出, wait 會等候直到有一個子進程退出。在上面的例子中,下面的兩行輸出

    parent: child=1234 child: exiting

    可能以任意順序被打印,這種順序由父進程或子進程誰先結束 printf 決定。當子進程退出時,父進程的 wait 也就返回
    了,于是父進程打印:

    parent: child 1234 is done

    需要留意的是父子進程擁有不同的內存空間和寄存器,改變一個進程中的變量不會影響另一個進程。
    系統調用 exec 將從某個文件(通常是可執行文件)里讀取內存鏡像,并將其替換到調用它的進程的內存空間。這份文件必
    須符合特定的格式,規定文件的哪一部分是指令,哪一部分是數據,哪里是指令的開始等等。xv6 使用 ELF 文件格式,第2
    章將詳細介紹它。當 exec 執行成功后,它并不返回到原來的調用進程,而是從ELF頭中聲明的入口開始,執行從文件中加載
    的指令。 exec 接受兩個參數:可執行文件名和一個字符串參數數組。舉例來說:

    char *argv[3]; argv[0] = "echo"; argv[1] = "hello"; argv[2] = 0; exec("/bin/echo", argv); printf("exec error\n");

    這段代碼將調用程序替換為 /bin/echo 這個程序,這個程序的參數列表為 echo hello 。大部分的程序都忽略第一個參數,這個參數慣例上是程序的名字(此例是 echo)。
    xv6 shell 用以上調用為用戶執行程序。shell 的主要結構很簡單,詳見 main 的代(8001)。主循環通過 getcmd 讀取命令行的輸入,然后它調用 fork 生成一個 shell 進程的副本。父 shell 調用 wait ,而子進程執行用戶命令。舉例來說,用戶在
    命令行輸入“echo hello”, getcmd 會以 echo hello 為參數調用 runcmd (7906), 由 runcmd 執行實際的命令。對于 echo hello , runcmd 將調用 exec 。如果 exec 成功被調用,子進程就會轉而去執行 echo 程序里的指令。在某個時刻 echo 會調用 exit ,這會使得其父進程從 wait 返回。你可能會疑惑為什么 fork 和 exec 為什么沒有被合并成一個調用,我們之后將會發現,將創建進程——加載程序分為兩個過程是一個非常機智的設計。
    xv6 通常隱式地分配用戶的內存空間。 fork 在子進程需要裝入父進程的內存拷貝時分配空間, exec 在需要裝入可執行文件時分配空間。一個進程在需要額外內存時可以通過調用 sbrk(n) 來增加 n 字節的數據內存。 sbrk 返回新的內存的地址。
    xv6 沒有用戶這個概念當然更沒有不同用戶間的保護隔離措施。按照 Unix 的術語來說,所有的 xv6 進程都以 root 用戶執行

    I/O 和文件描述符

    文件描述符是一個整數,它代表了一個進程可以讀寫的被內核管理的對象。進程可以通過多種方式獲得一個文件描述符,如打開文件、目錄、設備,或者創建一個管道(pipe),或者復制已經存在的文件描述符。簡單起見,我們常常把文件描述符指向的對象稱為“文件”。文件描述符的接口是對文件、管道、設備等的抽象,這種抽象使得它們看上去就是字節流。
    每個進程都有一張表,而 xv6 內核就以文件描述符作為這張表的索引,所以每個進程都有一個從0開始的文件描述符空間。
    按照慣例,進程從文件描述符0讀入(標準輸入),從文件描述符1輸出(標準輸出),從文件描述符2輸出錯誤(標準錯誤輸出)。我們會看到 shell 正是利用了這種慣例來實現 I/O 重定向。shell 保證在任何時候都有3個打開的文件描述符(8007),他們是控制臺(console)的默認文件描述符。
    系統調用 read 和 write 從文件描述符所指的文件中讀或者寫 n 個字節。 read(fd, buf, n) 從 fd 讀最多 n 個字節( fd 可能沒有 n 個字節),將它們拷貝到 buf 中,然后返回讀出的字節數。每一個指向文件的文件描述符都和一個偏移關聯。 read 從當前文件偏移處讀取數據,然后把偏移增加讀出字節數。緊隨其后的 read 會從新的起點開始讀數據。當沒有數據可讀時, read 就會返回0,這就表示文件結束了。

    write(fd, buf, n) 寫 buf 中的 n 個字節到 fd 并且返回實際寫出的字節數。如果返回值小于 n 那么只可能是發生了錯誤。
    就像 read 一樣, write 也從當前文件的偏移處開始寫,在寫的過程中增加這個偏移。

    下面這段程序(實際上就是 cat 的本質實現)將數據從標準輸入復制到標準輸出,如果遇到了錯誤,它會在標準錯誤輸出輸
    出一條信息。

    總結

    以上是生活随笔為你收集整理的xv6中文文档的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。