Xv6 chapter 0 學習筆記

2021-08-26 05:35:00 字數 3178 閱讀 7244

xv 6 chapter 0

operating system inte***ces

作業系統的工作是分享電腦資源給多個程式,並且提供一系列服務而不是只讓硬體提供。

作業系統通過介面給使用者程式提供服務,所以設計乙個好的介面就顯得很重要。

這裡作業系統xv6提供基礎的介面,由ken thompson 和dennis ritchie的作業系統介紹,同時還有模仿unix的內部設計。

每乙個執行的程式叫做程序,他們都有自己的空間,其中包括指令,資料和棧。指令實現了程式的計算功能,資料是那些計算中的變數。而棧則決定了程式的執行。

當乙個程序需要請求核心指令的時候,他會在作業系統的介面中請求乙個程式。這樣的程式叫做系統呼叫。系統呼叫進入到核心,核心就提供服務並且返回。因此乙個程序在使用者記憶體和核心記憶體中互相切換。

核心使用cpu的硬體保護機制來保證每個程序在使用者記憶體中執行並只能訪問自己的空間。核心執行的時候利用硬體提供的特權來實現這些保護,同時使用者程式沒有這些優先權。當乙個使用者程式請求系統呼叫的時候,這個硬體就提公升他的優先順序並執行乙個在核心實現安排好的程式。

processes and memory

int pid = fork();

if(pid > 0) else

if(pid == 0) else

exit系統呼叫會讓程序停止執行並釋放資源,比如記憶體和開啟的檔案等。wait系統呼叫返回乙個當前程序退出的子程序pid,如果當前程序的所有子程序都沒有退出,wait函式將會一直等待。

exec系統呼叫會把當前程序的記憶體空間從檔案系統中替換成乙個新的記憶體。這樣的檔案一定要特定的格式,比如明確哪一部分儲存指令,哪一部分是資料,從哪個指令開始等等。xv6使用elf格式。當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」。大部分的程式無視第乙個引數,因為一般來所只是程式的名字。

xv6隱式的分配大部分的使用者記憶體空間:fork 分配子程序複製父程序所需要的記憶體,exec為可執行檔案分配足夠的記憶體。乙個程序在執行的時候需要更多記憶體的時候可以呼叫sbrk(n)去增加n個位元組。sbrk返回新記憶體的位址。

xv6不提供使用者這個概念,或者保護每乙個使用者。在unix的角度,所有的xv6程序都是以root使用者來執行。

i/o and file descriptors

乙個檔案描述符是乙個很小的整數,表示乙個由核心管理的東西(object),並且程序可以讀寫。乙個程序也可以通過開啟乙個檔案,目錄,或者乙個裝置,又或者建立乙個管道,複製乙個已存在的描述符等等來很多方法獲得檔案描述符。簡單來說我們經常把乙個指向乙個東西(object)的描述符當做檔案「file」。檔案描述符的介面抽象並將檔案,管道還有裝置都看作一樣的字元流。

在內部,xv6核心使用檔案描述符當做在程序表中的查詢指引。所以每個程序都有檔案描述符的私有空間,檔案描述符由0開始。一般來說,程序從檔案描述符0(standard input 標準輸入)中讀取,從檔案描述符1(standard input 標準輸入)中寫入,從檔案描述符2(standard error 標準錯誤輸入)寫入錯誤資訊。正如我們所知,shell利用這些慣例來實現i/o的重定向和管道。shell確保了時刻都會有三個檔案描述符開啟,這些已經被控制台預設。

close系統呼叫會釋放檔案描述符,並且讓它可以被以後的open和pipe或者dup系統呼叫再次使用。乙個新建立的檔案描述符總是從該程序中沒用過的最小數字開始。

檔案描述符和fork共同使得i/o重定向容易被實現。fork複製父程序的記憶體和檔案描述,所以子程序的檔案描述符從和父程序一樣的地方開始計算。exec系統呼叫替換了當前程序的記憶體但是儲存了它的檔案表。這樣就允許shell利用fork實現了i/o重定向,並且重新開啟之前選擇的檔案描述符,然後執行新的程式。一下是乙個簡單的在shell執行命令cat命令command cat < input.txt:的例子

char *argv[2];

argv[0] = "cat";

argv[1] = 0;

if(fork() == 0)

在子程序關閉檔案描述符0之後,open就能確保使用的是新開啟的檔案input.txt,0將會是最小的可利用的檔案描述符。cat之後再執行檔案描述符0並指向input.txt。

儘管fork複製檔案描述符表,每個潛在的檔案偏移量也會在父子程序中共享。這是乙個例子:

if(fork() == 0)  else
dup系統呼叫可以複製乙個已存在的檔案描述符,返回乙個新的並且指向相同。兩個檔案共享偏移量就如同檔案描述符被fork複製一樣。這是另一種方法寫:

fd = dup(1);

write(1, "hello ", 6);

write(fd, "world\n", 6);

兩個檔案共享偏移量僅僅當他們被同乙個檔案dup或者fork,即使open開啟同乙個檔案也不會共享偏移量。

pipes

管道是乙個小的核心緩衝區,讓一對檔案描述符使用。乙個是來讀乙個是用來寫。一下是乙個例子:

int p[2];

char *argv[2];

argv[0] = "wc";

argv[1] = 0;

pipe(p);

if(fork() == 0) else

剛關閉檔案描述符0或者1的時候,dup分配最小可利用的描述符,也就是剛關閉的

如果所有指向write的描述符都被關閉,read將會返回0。事實上read一直阻塞直到關閉管道的寫端。如果wc的檔案描述符指向管道的寫端,wc將會永遠讀不到檔案結尾。

有些地方翻譯的不是很到位,如果有錯誤歡迎指出謝謝。後續還會有xv6的原始碼閱讀。

MIT 6 828 xv6學習筆記 0

vx6是mit開發的教學用的小型作業系統,是unix version 6 v6 的重新實現,這個筆記會摘抄xv6中文文件 以下簡稱 文件 的內容,同時結合一些自己的看法,文章遵循文件中的順序。1 在文件中,這樣定義作業系統的作用 作業系統的工作是 1 將計算機的資源在多個程式間共享,並且給程式提供一...

CUDA學習 Chapter 0 綜述

其實書上並沒有第0章啦,這篇東西是我自己寫的,談談cuda到底是什麼,以及cuda的基本使用和c之間的同異。平行計算,是一種和序列計算有著本質區別的運算。根據傳統的計算機計算的理論,計算機處理的資料分為兩種,指令流和資料流,因此就有幾種不同的計算方式 1.sisd,單指令單資料,也就是乙個指令對應乙...

xv6學習筆記 分頁機制 和記憶體管理

mmu.h原始碼中給出了xv6虛擬位址的構成,及所代表的含義 mmu.h中還有頁表的相關資訊,每個頁目錄都與1024條記錄,每乙個頁表中也有1024條記錄,每一頁的大小4096位元組,也就是4kb。page directory and page table constants.define npde...