溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

s081[1]-操作系統(tǒng)原理

發(fā)布時間:2020-02-14 11:10:16 來源:網(wǎng)絡(luò) 閱讀:255 作者:jonson_jackson 欄目:開發(fā)技術(shù)

操作系統(tǒng)

操作系統(tǒng)接口

前言

實驗1需要我們調(diào)用unix操作系統(tǒng)保持出的接口,因此首先需要了解unix操作系統(tǒng)有關(guān)的知識。

操作系統(tǒng)(operating system)的功能

  • 操作系統(tǒng)的任務(wù)是在多個程序之間共享一臺計算機,并提供比單獨的硬件所支持的更為有用的服務(wù)集。

  • 操作系統(tǒng)管理和抽象化低級硬件,因此,例如,文字處理器不必?fù)?dān)心自己正在使用哪種類型的硬件。

  • 操作系統(tǒng)允許多個程序之間共享硬件,以便它們可以并發(fā)運行。

  • 最后,操作系統(tǒng)提供了程序交互的方式,以便它們可以共享數(shù)據(jù),協(xié)同工作。

  • 操作系統(tǒng)為用戶程序提供接口去調(diào)用。設(shè)計一個好的接口操作系統(tǒng)接口非常困難。

  • 一方面希望簡單,一方面又希望實現(xiàn)復(fù)雜的功能。

  • 一種好的設(shè)計思路是接口之間可以通過某種機制組合起來以實現(xiàn)復(fù)雜的操作。

  • 本實驗中,使用了xv6 操作系統(tǒng)。其提供了unix的基本操作系統(tǒng)接口,并且模仿了Unix的內(nèi)部設(shè)計。

  • unix提供的接口很少,但是由于其可以組合的機制,提供了難以想象的通用性。該接口非常成功,以至于現(xiàn)代操作系統(tǒng)(BSD,Linux,Mac OS X,Solaris,甚至在較小程度上是Microsoft Windows)都具有類似Unix的接口。了解xv6是了解這些系統(tǒng)和許多其他系統(tǒng)的良好起點。

  • 內(nèi)核是操作系統(tǒng)的核心,為運行的程序提供服務(wù)。 每個正在運行的程序(稱為進程)都具有包含指令,數(shù)據(jù)和堆棧的內(nèi)存。

  • 指令說明了程序的運行邏輯。數(shù)據(jù)是指令運行所需要的變量。堆棧組織程序的過程調(diào)用。

  • 當(dāng)進程需要調(diào)用內(nèi)核服務(wù)時,它將通過操作系統(tǒng)提供的接口進行過程調(diào)用。 這樣的過程稱為系統(tǒng)調(diào)用。

  • 內(nèi)核使用CPU的硬件保護機制來確保在用戶空間中執(zhí)行的每個進程只能訪問其自己的內(nèi)存。

  • 用戶程序調(diào)用操作系統(tǒng)接口后,硬件提高權(quán)限級別,并開始在內(nèi)核中執(zhí)行預(yù)先安排的功能。

  • shell是一個普通程序,可讀取用戶命令并執(zhí)行命令。 shell是用戶程序而不是內(nèi)核的一部分,這一事實說明了操作系統(tǒng)接口的強大功能。shell沒有什么特別之處,這也意味著shell易于更換;現(xiàn)代Unix系統(tǒng)有多種shell可供選擇,每種shell都有其自己的用戶界面和腳本功能。 xv6 shell是Unix Bourne shell的簡單實現(xiàn)。 可以在(user / sh.c:1)中找到其實現(xiàn)。

操作系統(tǒng)接口

  • xv6進程由用戶空間內(nèi)存(指令,數(shù)據(jù)和堆棧)和內(nèi)核專有的每個進程狀態(tài)組成。

  • xv6保證進程的并發(fā)執(zhí)行,在多個進程之間切換CPU能力。

  • 當(dāng)某個進程未執(zhí)行時,xv6保存其CPU寄存器,并在下次運行該進程時恢復(fù)它們。 內(nèi)核將進程標(biāo)識符或pid與每個進程相關(guān)聯(lián)。

  • 進程可以使用fork系統(tǒng)調(diào)用來創(chuàng)建新進程。 Fork創(chuàng)建一個稱為子進程的新進程,該進程與父進程的內(nèi)存完全相同。

  • Fork在子進程與父進程中都會返回。

  • 在父進程中,fork返回子進程的pid; 在子進程中,它返回零。
    例如,考慮以下用C編程語言編寫的程序片段:

int?pid?=?fork();
if(pid?>?0){
????printf("parent:?child=%d\en",?pid);
????pid?=?wait(0);
????printf("child?%d?is?done\en",?pid);
}?else?if(pid?==?0){
????printf("child:?exiting\en");
????exit(0);
}?else?{
????printf("fork?error\en");
}
  • exit導(dǎo)致調(diào)用進程停止執(zhí)行并釋放資源,例如內(nèi)存和打開的文件。

  • exit接受一個整數(shù)狀態(tài)參數(shù),通常0表示成功,1表示失敗。

  • wait系統(tǒng)調(diào)用返回當(dāng)前進程已退出子進程的pid,并將該子進程的退出狀態(tài)傳遞給wait。

  • 如果子進程都沒有退出,一直會等待。

  • 如果父進程不在乎子進程的退出狀態(tài),則可以傳遞狀態(tài)0。

在下面的例子中,輸出是:

  • parent: child=1234

  • child: exiting

也可能出現(xiàn)另外的情況,具體取決于父進程還是子進程首先進入其printf調(diào)用。

  • 子進程退出后,父進程的wait返回,導(dǎo)致父進程打印出:

  • parent: child 1234 is done。

  • 盡管子進程最初具有與父進程相同的內(nèi)存內(nèi)容,但是父進程和子進程執(zhí)行時使用的是不同的內(nèi)存和不同的寄存器。

  • 更改一個變量不會影響另一個變量。

  • 例如,當(dāng)wait的返回值在父進程中存儲到pid中時,它不會更改子進程中的pid。 子進程中的pid的值仍為零。

  • exec系統(tǒng)調(diào)用使用從文件系統(tǒng)中存儲的文件加載的新的內(nèi)存映像替換調(diào)用進程的內(nèi)存。

  • 該文件必須具有特定的格式,該格式指定文件的哪一部分包含指令,哪一部分是數(shù)據(jù),從哪條指令開始等。

  • xv6使用ELF格式,第3章將對此進行詳細(xì)討論。

  • 當(dāng)exec成功執(zhí)行時,它不會返回到調(diào)用程序。從文件加載的指令在ELF標(biāo)頭中聲明的入口點開始執(zhí)行。

  • Exec接受兩個參數(shù):包含可執(zhí)行文件的文件名和一個字符串參數(shù)數(shù)組。 例如:

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

該片段將調(diào)用程序以程序/ bin / echo的實例替換,參數(shù)列表為echo hello。 大多數(shù)程序會忽略第一個參數(shù),這通常是程序的名稱

  • xv6 Shell使用上述調(diào)用執(zhí)行用戶運行的程序。

  • xv6 Shell使用上述調(diào)用代表用戶運行程序。

  • shell的主要結(jié)構(gòu)很簡單; 參見main(user / sh.c:145)。

  • 主循環(huán)使用getcmd從用戶讀取一行輸入。 然后,它將調(diào)用fork,這將創(chuàng)建shell進程的副本。

  • 父進程調(diào)用wait,而子進程運行命令。 例如,如果用戶鍵入“ echo hello”給shell,則將以“ echo hello”作為參數(shù)調(diào)用runcmd。 runcmd(user / sh.c:58)運行實際命令

  • 對于“ echo hello”,它將調(diào)用exec(user / sh.c:78)

  • 如果exec成功,則子進程將從echo執(zhí)行指令,而不是runcmd。

  • 在某些時候,echo將調(diào)用exit,這將導(dǎo)致父進程從main(user / sh.c:145)的wait中返回。

  • 您可能想知道為什么fork和exec不能在單個調(diào)用中組合? 稍后我們將看到,用于創(chuàng)建進程和加載程序的單獨調(diào)用在Shell中用于I / O重定向的用法很巧妙。

  • 為了避免創(chuàng)建重復(fù)進程然后立即替換它的浪費,運行中的內(nèi)核通過使用虛擬內(nèi)存技術(shù)(如copy-on-write 寫時復(fù)制)來針對此用例優(yōu)化fork的實現(xiàn)。

  • Xv6隱式分配了大多數(shù)用戶空間內(nèi)存:fork分配了子進程復(fù)制父進程所需的內(nèi)存,而exec分配了足夠的內(nèi)存來保存可執(zhí)行文件。

  • 一個在運行時需要更多內(nèi)存的進程(可能是malloc)可以調(diào)用sbrk(n)將其數(shù)據(jù)內(nèi)存增加n個字節(jié)。 sbrk返回新內(nèi)存的位置。

  • Xv6沒有提供用戶概念來保護一個用戶免受另一個用戶侵害;用Unix術(shù)語,所有xv6進程都以root身份運行。

I/O 與文件描述符

*?文件描述符是一個小的整數(shù),表示進程可以從中讀取或?qū)懭氲膬?nèi)核管理的對象。?進程可以通過打開文件,目錄或設(shè)備,或通過創(chuàng)建管道,或通過復(fù)制現(xiàn)有描述符來獲取文件描述符。?為簡單起見,我們通常將文件描述符所指的對象稱為“文件”;?文件描述符接口抽象了文件,管道和設(shè)備之間的差異,使它們看起來都像字節(jié)流。
*?在內(nèi)部,xv6內(nèi)核使用文件描述符作為每個進程表的索引,因此每個進程都有一個從零開始的文件描述符專用空間。?按照慣例,進程從文件描述符0(標(biāo)準(zhǔn)輸入)讀取,將輸出寫入文件描述符1(標(biāo)準(zhǔn)輸出),并將錯誤消息寫入文件描述符2(標(biāo)準(zhǔn)錯誤)。?就像我們將看到的那樣,shell利用約定來實現(xiàn)I?/?O重定向(redirection)和管道(pipelines)。?shell確保始終打開三個文件描述符(user?/?sh.c:151),默認(rèn)情況下,這三個文件描述符是控制臺(console)的文件描述符。
  • read系統(tǒng)調(diào)用從文件描述符讀取字節(jié)。

  • write系統(tǒng)調(diào)用從文件描述符寫入字節(jié)。

  • 調(diào)用read(fd,buf,n)最多從文件描述符fd中讀取n個字節(jié),將它們復(fù)制到buf中,并返回讀取的字節(jié)數(shù)。 引用文件的每個文件描述符都有一個與之關(guān)聯(lián)的偏移量。read從當(dāng)前文件偏移量讀取數(shù)據(jù),隨著讀取到的數(shù)據(jù)增加,文件的偏移量隨之增加。當(dāng)沒有更多字節(jié)可以讀取時,read將返回零以指示文件末尾。

  • 調(diào)用write(fd,buf,n)將buf中的n個字節(jié)寫入文件描述符fd,并返回寫入的字節(jié)數(shù)。 僅在發(fā)生錯誤時才寫入少于n個字節(jié)。 與讀操作類似,寫操作會在當(dāng)前文件偏移量處寫入數(shù)據(jù),然后將偏移量增加寫入的字節(jié)數(shù):每次寫操作都從上次中止的位置開始。

  • 以下程序片段(cat命令的功能)將數(shù)據(jù)從其標(biāo)準(zhǔn)輸入復(fù)制到其標(biāo)準(zhǔn)輸出。 如果發(fā)生錯誤,它將向標(biāo)準(zhǔn)錯誤寫入一條消息。

char?buf[512];
int?n;
for(;;){
????n?=?read(0,?buf,?sizeof?buf);
????if(n?==?0)
????break;
????if(n?<?0){
????????fprintf(2,?"read?error\en");
????????exit();
????}
????if(write(1,?buf,?n)?!=?n){
????????fprintf(2,?"write?error\en");
????????exit();
????}
}

在代碼片段中要注意的重要一點是cat不知道它是從文件,控制臺還是管道中讀取。?同樣,cat不知道它是要打印到控制臺,文件還是其他地方。?使用文件描述符以及文件描述符0是標(biāo)準(zhǔn)輸入和輸出文件描述符是標(biāo)準(zhǔn)輸出的約定可以實現(xiàn)cat的簡單實現(xiàn)。close系統(tǒng)調(diào)用將釋放文件描述符,以供將來的open,pipe或dup系統(tǒng)調(diào)用重用。?新分配的文件描述符始終是當(dāng)前進程中編號最小的未使用的描述符。

文件描述符和fork交互使I/O重定向易于實現(xiàn)。Fork會復(fù)制父文件的文件描述符表及其內(nèi)存,以便子文件與父文件打開完全相同的文件。 exec系統(tǒng)調(diào)用替換了調(diào)用進程的內(nèi)存,但保留了其文件表。 此行為允許Shell通過分叉,重新打開選定的文件描述符,然后exec新程序來實現(xiàn)I / O重定向。 這是shell為cat <input.txt命令運行的代碼的簡化版本:

char?*argv[2];
????argv[0]?=?"cat";
????argv[1]?=?0;
????if(fork()?==?0)?{
????????close(0);
????????open("input.txt",?O_RDONLY);
????????exec("cat",?argv);
????}
  • 當(dāng)child關(guān)閉文件描述符0后,0 是最小的文件描述符。因此open操作將使文件描述符0(標(biāo)準(zhǔn)輸入)指向文件input.txt.xv6 shell中的I / O重定向代碼完全以這種方式工作(user / sh.c:82)。

  • 現(xiàn)在應(yīng)該清楚為什么將fork和exec分開調(diào)用是一個好主意? 因為如果它們是分開的,則shell可以fork一個child,在該child中使用open,close,dup來更改標(biāo)準(zhǔn)輸入和輸出文件描述符,然后exec。 不需要更改正在執(zhí)行的程序(在我們的示例中為cat)。 如果將fork和exec組合到單個系統(tǒng)調(diào)用中,則shell將需要一些其他(可能更復(fù)雜)的方案來重定向標(biāo)準(zhǔn)輸入和輸出,或者程序本身將必須了解如何重定向I / O。

  • 盡管fork復(fù)制了文件描述符表,但每個潛在文件的偏移量在父級和子級之間共享。 考慮以下示例:

if(fork()?==?0)?{
????write(1,?"hello?",?6);
????exit(0);
}?else?{
????wait(0);
????write(1,?"world\en",?6);
}
  • 在上例中,父進程和子進程都將寫入文件描述符1.最后輸出的數(shù)據(jù)是"hello world"

  • 父進程的寫入會等到子進程寫入后進行(由于wait)。兩個文件描述符共享一個偏移量。

  • 此行為有助于從Shell命令序列產(chǎn)生順序輸出,例如(echo hello; echo world)> output.txt。

  • dup系統(tǒng)調(diào)用復(fù)制了一個現(xiàn)有的文件描述符,并返回了一個新的文件描述符,該描述符引用了相同的潛在I/O對象。兩個文件描述符共享一個偏移量,就像fork所復(fù)制的文件描述符一樣。這是將hello world寫入文件的另一種方法:

fd?=?dup(1);
write(1,?"hello?",?6);
write(fd,?"world\en",?6);
  • 如果兩個文件描述符是通過fork和dup調(diào)用序列從同一原始文件描述符派生的,則它們共享一個偏移量。 否則,文件描述符不共享偏移量,即使它們是對同一文件的open產(chǎn)生的。 Dup允許shell執(zhí)行以下命令: ls existing-file non-existing-file > tmp1 2>&1。 2>&1告訴shell將文件描述符2與描述符1相同。已存在文件的名稱和文件不存在等錯誤消息都將顯示在文件tmp1中。 xv6 Shell不支持錯誤文件描述符的I / O重定向,但是現(xiàn)在您知道如何實現(xiàn)它。

  • 文件描述符是一種強大的抽象,因為它們隱藏了它們所連接的對象的詳細(xì)信息:寫入文件描述符1的進程可能正在寫入文件,諸如控制臺的設(shè)備或管道。

管道

  • 管道是一個小的內(nèi)核緩沖區(qū),以一對文件描述符的形式暴露給進程,一個用于讀取,一個用于寫入。

  • 將數(shù)據(jù)寫入管道的一端可使該數(shù)據(jù)可從管道的另一端讀取。 管道為流程進行通信提供了一種方法。 以下示例代碼運行程序wc,使用標(biāo)準(zhǔn)輸入連接到管道的讀取端。

int?p[2];
char?*argv[2];
argv[0]?=?"wc";
argv[1]?=?0;
pipe(p);
if(fork()?==?0)?{
????close(0);
????dup(p[0]);
????close(p[0]);
????close(p[1]);
????exec("/bin/wc",?argv);
}?else?{
????close(p[0]);
????write(p[1],?"hello?world\en",?12);
????close(p[1]);
}

*?程序調(diào)用pipe創(chuàng)建一個新管道,并將讀取和寫入文件描述符記錄在數(shù)組p中。?在fork之后,父進程和子進程都具有引用管道的文件描述符。?子進程將讀取端復(fù)制到文件描述符0上,關(guān)閉p中的文件描述符,然后執(zhí)行wc。?當(dāng)wc從其標(biāo)準(zhǔn)輸入中讀取時,它將從管道中讀取。?父進程關(guān)閉管道的讀取側(cè),寫入管道,然后關(guān)閉寫入側(cè)。
  • 如果沒有可用數(shù)據(jù),則在管道上進行讀取以等待寫入數(shù)據(jù)或所有引用寫入端的文件描述符被關(guān)閉; 在后一種情況下,讀取將返回0,就像到達數(shù)據(jù)文件的末尾一樣。 讀取管道會一直堵塞直到無法接受到數(shù)據(jù)。因此,對于子進程來說,在執(zhí)行上述wc之前關(guān)閉管道的寫端很重要:如果wc進程的文件描述符之一引用了管道的寫端,則wc將永遠(yuǎn)等不到文件末尾 。

  • xv6 shell實現(xiàn)了管道,例如grep fork sh.c | wc -l 類似于上面的代碼(user / sh.c:100)。 子進程創(chuàng)建一個管道,以將管道的左端與右端連接起來。 然后,它在管道的左端調(diào)用fork和runcmd,在右端調(diào)用fork和runcmd,并等待兩者都完成。 管道的右端可能是一個命令,該命令本身包括一個管道(例如a | b | c),該管道本身派生了兩個新的子進程(一個用于b,一個用于c)。 因此,shell可以創(chuàng)建進程樹。 該樹的葉子是命令,內(nèi)部節(jié)點是等待左右子節(jié)點完成的進程。 原則上,您可以讓內(nèi)部節(jié)點在管道的左端運行,但是這樣做會使實現(xiàn)復(fù)雜化。

  • 管道似乎沒有臨時文件強大:echo hello world | wc

  • 可以在沒有管道的情況下實現(xiàn):
    echo hello world >/tmp/xyz; wc </tmp/xyz

  • 在這種情況下,管道比臨時文件至少具有四個優(yōu)點。 首先,管道會自動清理自己; 使用文件重定向,shell必須在完成后小心刪除/ tmp / xyz。 其次,管道可以傳遞任意長的數(shù)據(jù)流,而文件重定向需要磁盤上有足夠的可用空間來存儲所有數(shù)據(jù)。 第三,管道允許并行執(zhí)行管道階段,而文件方法要求第一個程序在第二個程序啟動之前完成。 第四,如果要實現(xiàn)進程間通信,則管道的讀寫鎖比文件的 non-blocking語義更有效。

文件系統(tǒng)

  • xv6文件系統(tǒng)提供了數(shù)據(jù)文件和目錄,這些數(shù)據(jù)文件是原始的字節(jié)數(shù)組。目錄包含對數(shù)據(jù)文件和其他目錄的命名引用。 目錄形成一棵樹,從一個特殊的root目錄開始。

  • 類似于/a/b/c的路徑是指根目錄/中名為a的文件夾中名為b的文件夾中名為c的文件或文件夾。

  • 不以/開頭的路徑是相對于調(diào)用進程的當(dāng)前目錄的。調(diào)用進程的當(dāng)前目錄可以通過chdir系統(tǒng)調(diào)用對其進行更改。

  • 下面這兩個程序片段都打開同一個文件(假設(shè)文件存在)

chdir("/a");
chdir("b");
open("c",?O_RDONLY);

open("/a/b/c",?O_RDONLY);
  • 第一個代碼片段將進程的當(dāng)前目錄更改為/a /b; 第二個既不引用也不更改進程的當(dāng)前目錄。

  • 有多個操作系統(tǒng)接口來創(chuàng)建新文件或文件夾:mkdir創(chuàng)建新文件夾,使用O_CREATE標(biāo)志調(diào)用open將創(chuàng)建新數(shù)據(jù)文件,而mknod將創(chuàng)建新設(shè)備文件。 如下例所示:

mkdir("/dir");
fd?=?open("/dir/file",?O_CREATE|O_WRONLY);
close(fd);
mknod("/console",?1,?1);

Mknod在文件系統(tǒng)中創(chuàng)建一個文件,但是該文件沒有內(nèi)容。 但是,文件的元數(shù)據(jù)會將其標(biāo)記為設(shè)備文件,并記錄主設(shè)備號和次設(shè)備號(mknod的兩個參數(shù)),它們唯一地標(biāo)識內(nèi)核設(shè)備。 當(dāng)以后有一個進程打開文件時,內(nèi)核會將read和write系統(tǒng)調(diào)用轉(zhuǎn)換到內(nèi)核設(shè)備的讀寫實現(xiàn),而不是將它們轉(zhuǎn)換到文件系統(tǒng)。

fstat系統(tǒng)調(diào)用得到有關(guān)文件描述符引用的對象的信息。此對象信息返回結(jié)構(gòu)體stat,定義在
stat.h (kernel/stat.h):

#define?T_DIR?1?//?Directory
#define?T_FILE?2?//?File
#define?T_DEVICE?3?//?Device
struct?stat?{
????int?dev;?//?File?system’s?disk?device
????uint?ino;?//?Inode?number
????short?type;?//?Type?of?file
????short?nlink;?//?Number?of?links?to?file
????uint64?size;?//?Size?of?file?in?bytes
};

文件名與文件不同; 同一個文件(稱為inode)可以具有多個名稱(稱為links)。
link系統(tǒng)調(diào)用將創(chuàng)建另一個文件名稱,該名稱引用與現(xiàn)有文件相同的inode。 下面的程序片段創(chuàng)建了一個名為a又為b的新文件。

open("a",?O_CREATE|O_WRONLY);
link("a",?"b");

讀取,寫入a與讀取,寫入到b相同。 每個inode由唯一的inode編號標(biāo)識。 在上面的代碼片段之后,可以通過檢查fstat的結(jié)果確定a和b是否引用相同的文件:兩者將返回相同的inode編號(ino),并且nlink將變?yōu)?。

unlink系統(tǒng)調(diào)用從文件系統(tǒng)中刪除一個名稱。 僅當(dāng)文件的link計數(shù)為零且沒有文件描述符引用該文件時, 才會將inode和其所在的磁盤空間清除。

因此當(dāng)執(zhí)行了

unlink("a");

之后,使用名稱b任然能夠訪問文件。

下面的程序片段是一種慣用的方式創(chuàng)建一個臨時inode。

fd?=?open("/tmp/xyz",?O_CREATE|O_RDWR);
unlink("/tmp/xyz");
  • 當(dāng)fd文件描述符被關(guān)閉后,臨時的inode將會被清除。

  • 用于文件系統(tǒng)操作的Shell命令是作為用戶級程序(例如mkdir,ln,rm等)實現(xiàn)的。該設(shè)計允許任何人通過添加新的用戶程序擴展Shell。在事后看來,似乎是理所當(dāng)然的。

  • 但和Unix同時期的其他系統(tǒng)設(shè)計,通常將這樣的命令構(gòu)建到shell中(并將shell構(gòu)建到內(nèi)核中)。

  • cd是一個例外,它內(nèi)置在shell中(user / sh.c:160)。 cd必須更改shell本身的當(dāng)前工作目錄。 如果cd以常規(guī)命令運行,那么shell將派生一個子進程,該子進程將運行cd,而cd會更改該子進程的工作目錄。 父進程(即shell)的工作目錄不會更改。

總結(jié)

Unix結(jié)合了文件描述符,管道和方便的shell語法以對其進行操作,這是編寫通用可復(fù)用程序的重大進步。這是Unix的強大功能和廣泛使用的原因,外殼程序是第一種所謂的“腳本語言”。Unixit系統(tǒng)調(diào)用接口在BSD,Linux,和Mac OSX 上廣泛使用。

  • Unix系統(tǒng)調(diào)用接口已通過可移植操作系統(tǒng)接口(POSIX)標(biāo)準(zhǔn)進行了標(biāo)準(zhǔn)化。 Xv6不兼容POSIX。 它拋棄一些了系統(tǒng)調(diào)用(包括諸如lseek之類的基本調(diào)用),僅部分實現(xiàn)了系統(tǒng)調(diào)用以及其他差異。 xv6的主要目標(biāo)是簡單性和清晰度,同時提供簡單的類UNIX系統(tǒng)調(diào)用接口。 為了運行基本的Unix程序,一些人用更多的系統(tǒng)調(diào)用和一個簡單的C庫擴展了xv6。 但是,與xv6相比,現(xiàn)代內(nèi)核提供了更多的系統(tǒng)調(diào)用和內(nèi)核服務(wù)。 例如,它們支持聯(lián)網(wǎng),窗口系統(tǒng),用戶級線程,許多設(shè)備的驅(qū)動程序等。 現(xiàn)代內(nèi)核不斷快速發(fā)展,并提供了POSIX以外的許多功能。

  • 在很大程度上,現(xiàn)代Unix派生的操作系統(tǒng)沒有遵循早期的Unix模型,即將設(shè)備公開為特殊文件,例如上面討論的控制臺設(shè)備文件。Unix的作者繼續(xù)構(gòu)建Plan9,將“資源即文件”概念應(yīng)用于現(xiàn)代設(shè)施,將網(wǎng)絡(luò),圖形和其他資源表示為文件或文件樹。

  • 文件系統(tǒng)和文件描述符是強大的抽象。 即使這樣,也存在其他模型。 Multics是Unix的前身,它以一種類似于內(nèi)存的方式抽象了文件存儲,從而產(chǎn)生了截然不同的界面風(fēng)格。 Multics設(shè)計的復(fù)雜性直接影響了Unix的設(shè)計師,后者試圖構(gòu)建更簡單的東西。

  • 本書探討了xv6如何實現(xiàn)其類似Unix的接口,但是這些思想和概念不僅適用于Unix。 任何操作系統(tǒng)都必須將進程多路復(fù)用到基礎(chǔ)硬件上,將進程彼此隔離,并提供用于受控的進程間通信的機制。 研究xv6之后,您應(yīng)該能夠查看其他更復(fù)雜的操作系統(tǒng),

參考資料

dreamerjonson.com/2020/
pdos.csail.mit.edu/6.82
pdos.csail.mit.edu/6.82
pdos.csail.mit.edu/6.82


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI