iT邦幫忙

2022 iThome 鐵人賽

DAY 2
1

前言

首先在最一開始,將藉由 Hello World 範例程式,引入一些作業系統的基本部件。以及作業系統的概念與目標,抽象性的實現,最後引入 System call 的概念,作業系統分層與總類。

When Hello World Running

以下為 C 語言的 Hello World

#include <stdio.h>

int main(void)
{
    printf("Hello World\n");
    return 0;
}

接著我們會通過 gcc 工具鍊,經過了前處理的巨集展開,經過編譯器 (c compiler, cc) 產生出組合語言,接著經過組譯器 (assembiler, as) 產生出目的碼檔案,最後鏈結器 (linker, ld) 鏈接其他檔案與函式庫後,產生出了可執行檔 hello.exe。

gcc hello.c -o hello

exe 包含了許多機械碼指令提供給 CPU,以及一些資料,而這些對於 CPU的機械指令,是由 CPU 的指令集架構 (Instruction Set Architecture, ISA) 所實現,而 CPU 還會包含一些暫存器,像是Program Counter (PC), 或是一些指令的運算元 (Operands), 記憶體地址等等資訊。

當執行一個可執行檔時,CPU 會進行以下

  • 讀取 Program Counter 並抓取 (fetch) 欲執行的指令位於記憶體中的位置,並將指令儲存到 Instruction Register (IR)。
  • 載入 IR 中的指令並且解碼後,載入指令要求的一些資料到暫存器中,並且執行指令。
  • 將執行的結果存回記憶體中。

(最近執行過的指令或是資料會放入 CPU 的快取中用來加速整個程式的執行)
而在上面這一些過程中,作業系統會進行以下工作。

  • 作業系統對 CPU :
    • 初始化 Program Counter 以及其他的暫存器開始執行程式,而對於一個執行中的程式,CPU 會使用 Process (處理程序) 進行描述,作業系統擁有一個 Process 的掌控權,並協調每一個 Process 之間的資源調度 (Timeshare),每一個 Process 會有一個虛擬的 CPU。
  • 作業系統對記憶體 :
    • 將程式碼以及一些 Data 從硬碟載入到記憶體中,而對於每一個 Process,作業系統會去維護他們的 Data, code, stack, heap 等等資訊,並且會提供虛擬記憶體的機制 (每一個 Process 的記憶體空間),以及虛擬記憶體與真實物理記憶體之間的轉換映射機制。
  • 作業系統對外部硬體裝置 :
    • 讀取以及寫入硬碟,作業系統會提供一些驅動程式讓程式以及硬體之間能夠進行互動,以及回應一些 I/O 中斷的需求 (像是等待鍵盤輸入等等)。以及在硬碟上提供檔案系統方便管理與組織檔案

作業系統概念與目標

電腦通常由一個或是多個 CPU 組成,包含 RAM,硬碟,鍵盤,滑鼠,螢幕等等,可見電腦是一個複雜的系統,而如果開發一隻程式需要掌握這全部的知識,會讓程式的開發變得十足的困難,因此,電腦上面有一個軟體,稱之為作業系統,提供了一個更為抽象,方便理解的電腦模型。

作業系統為一種可以管理電腦硬體的軟體,而這個軟體有幾個目標需要達成。

  • 抽象 (Abstraction) :
    將硬體抽象化,一部電腦中,會包含CPU, GPU, RAM等等,但這是站在看待硬體的角度去看待,也就是以相較low-level的角度看待,而在作業系統中,會提供相較high-level的角度去看待這一些硬體,諸如process(處理程序),file system(檔案系統)等等,可以方便軟體開發,以及提供軟體更好的可移植性。

  • 多工 (Multiplex) :
    現代作業系統需要在多個 process 之間共享資源,再不互相干擾的前提之下,同時執行這一些程式。例如三個程式需要在同一台影印機上輸出結果,可能會發生三個程式的輸出混雜在一起的情況發生,而這時候我們會需要一些處理的方式,像是將輸出輸出到緩衝區之後的方法。

  • 獨立性 (Isolation)
    如果應用程式發生了當機,崩潰等等,不會影響到其他應用程式,程式的活動之間必須不能互相干擾。

  • 共享 (Sharing)
    許多時候不同程式之間需要交換資料,傳送資料,共同完成任務等等,例如使用檔案系統建立的一個檔案,經由文字編輯器讀取與編輯,之後寫入並儲存,這時候便會需要共享。

  • 存取控制 (Access Control System)
    有時我們不希望使用者之間共享資源,或是其他使用者讀取我們的檔案,而這時候我們會希望有存取控制的手段給予限制。

  • 效率 (Efficiency)
    作業系統作為資源的協調以及管理者,期望能夠更有效(並非公平)的運用資源。

API(應用程式介面)概念:

假設我到麥當勞想要點一個大麥克,我會走到櫃台和服務人員點一個大麥克,而經過了3分鐘後,大麥克就會噴出來了,我不需要管大麥克是如何製作的,只要和服務人員說我要一個大麥克,服務人員就會噴一個大麥克,服務人員就是 API 的概念。

而假設我要搜尋一個檔案,我只需要通過檔案系統就可以找到目標檔案,不需要管應的讀寫頭該如何運動,或是需要運動到磁盤中的那一個位置,檔案系統就相當於一個 API,讓我們可以方便的直接得到目標檔案,API 為一個抽象思考的概念,可將複雜的系統簡化,方便程式開發。

以下為 C 語言 API 概念示範 :

//source : https://www.bottomupcs.com/abstration.xhtml
#include <stdio.h>

//greet_api class
struct greet_api
{
    int (*say_hello)(char *name);
    int (*say_goodbye)(void);
};

//member function implementation
int say_hello_func(char *name)
{
    printf("Hello %s\n", name);
    return 0;
}

//member function implementation
int say_goodbye_func(void)
{
    printf("Goodbye\n");
    return 0;
}

//object implementation
struct greet_api greet_api =
{
    .say_hello = say_hello_func,
    .say_goodbye = say_goodbye_func
};

int main(int argc, char *argv[])
{
    greet_api.say_hello(argv[1]);
    greet_api.say_goodbye();
    return 0;
}

execute:

./hello alice

output:

hello alice
goodbye

作業系統結構

整個作業系統包含了幾個部份,分別為 User Interface 的部份,像是 GUI, Shell 等等,和底層硬體進行互動的 kernel 部份。

而從硬體層,如 CPU,硬碟,到 process, file system 較高抽象層次,中間需要經過一個界面提供給使用者進行使用,類似於 API 的概念,而這個中間層就稱為 kernel。


< Kernel (operating system) >

我們可以對這一張圖進行分層:

  • User space : 執行各種應用程式,如 vim, C complier 等等
  • Kernel space : 有別於 User space 中各各應用程式,kernel這個程式在電腦開機時就會被開啟了,kernel中有許多服務用來維護以及管理底下硬體層的各各硬體。例如kernel中會有檔案系統,將檔案抽象成檔案名稱,檔案類型等等,以及檔案該如何儲存在硬碟之中,目錄結構等等。

每一個在 User space 中執行的程式,稱為一個 process,每一個 process 有自己的記憶體空間,包含一些 instruction, data, stack 等等資訊,instruction 用來實現程式的計算部份,data 為一個變數記錄計算時所發生的動作,stack 會紀錄程式對其他函數或是其他程式的呼叫。電腦中通常會有許多 process 正在執行,但皆是通過一個 kernel 進行管理。

在一個現代完整的作業系統中,kernel 中還會有許多的服務,像是處理 TCP/IP 協定,支援許多不同的網卡等等,所以一個 kernel 通常程式碼的數量是十分龐大的。

檔案系統為 kernel 提供和硬體層進行互動的 API,而對於 user space 和 kernel 層的互動,kernel 也提供了一些 API 進行互動,當 user space 中的 process 需要呼叫 kernel 所提供的服務時,稱為一個系統呼叫 (system call)。

在作業系統中,我們主要關注的部分是 kernel 的部分,正如前面所言,作業系統的角色是扮演使用者到硬體層面的溝通者,而在作業系統中主要負責這個部分的是 kernel,因此在作業系統的討論中會集中在 kernel 中各個功能的實踐,諸如記憶體管理等等。

System call概念

  • System call 為特殊的函式呼叫 (function call),可以讓我們執行一些高權限等級的作業系統指令。
  • 一些較為敏感的操作,如直接存取硬碟等操作需要在較高的權限模式下運作,如在 kernel mode 底下,這時候我們可以使用 System call 完成這一些操作。

如果有一個程式需要打開一個檔案,則會需要進行open的系統呼叫,將文件名稱以及一個"額外"參數 (Argument) 傳入open中,這個額外參數表示我想要對 "file" 這個檔案進行寫入的操作。

fd = open("file", 1);

這看起來像是一個普通的函式呼叫 (function call),但實際上這是一個系統呼叫,會跳轉到 kernel 中,執行 kernel 中實現open的程式碼,最後回傳一個 file descriptor,由 fd 變數所接受,fd 的全名為 file descriptor,之後,其他程式就可以通過 fd 來得知該如何對這個檔案進行操作,這個概念也被稱為 file handle。process 使用open的系統呼叫,user space 和 kernle space 會進行互動。

< from book-riscv >

事實上 C 語言的函式庫 (lib c) 的printf函式就隱藏了系統呼叫的部分,如果我們將printf展開,可以發現裡面存在 System call 的部分。

write(stdout, text);

< How Does the CPU Output “Hello, World!” To the Command Line >

System call 定義在user.h中,在 xv6 中支援21種 System call,System call 只能在 supervisor mode (kernel mode) 底下執行。

POSIX API

POSIX (Portable Operating System Interface of UNIX) 為一套 UNIX 的標準。

UNIX 為作業系統,在早期 AT&T 將 UNIX 作業系統以低廉的收費甚至免費授權給許多學術以及商業機構,許多機構在基於 UNIX 的基礎上進行一些改進而產生出新的作業系統,這一些作業系統被稱為 UNIX Like 的作業系統,而為了提高程式在這一些 UNIX Like 之間的可移植性,IEEE 制定了一套標準,稱為 POSIX。

POSIX 制定了關於 System call 的標準,符合 POSIX 標準的作業系統需要支援哪一些 System call,以及 C 語言函式庫,shell 等等一系列的標準。

Shell 概念

Shell 為一隻程式,接受使用者輸入的指令並且執行他們,Shell 為 user space 的程式,而非 Kernel 的一部分,可以從上圖中得知。在UNIX 中有許多的 Shell,諸如 bash, zsh,擁有自己的界面和一些腳本功能,之所以被稱作為 Shell 可以從上面這一張圖得知,他隱藏了Kernel (從殼到核心) 細節的部份,通過 Shell 去和 Kernel 互動。

Operating System Types (作業系統種類簡介)

Mutiprogramming system

定義 : 允許多個 Process 同時執行的 System。
目的 : 提高 CPU 使用率 (utilization),避免 CPU 處於閒置 (idel),等待使用者命令的狀態。
作法 : 利用 CPU 排班技術 (Schedualing) 來讓 CPU 可以在多個 Process 之間切換。
Process 同時執行使用兩種方法:

Concurrency execute (並行執行)

Concurrency,可以將一隻程式拆分成多個可獨立執行的工作,可以讓很多事情一起做,但是不一定真得要一起做,讓多個工作在單一個 CPU (或是單核 CPU) 上面執行。而可將程式拆分成多個部分,是屬於程式架構的部分。

< Introduction to OpenMP: 02 part 2 Module 1 >

Parallelism execute (平行執行)

Parallelism,是指可以同時執行多隻程式,把程式分配給不同的核心(多核處理器)(執行緒 thread, 在 RISC-V 中也會稱為 hart)

< Introduction to OpenMP: 02 part 2 Module 1 >

Time-sharing System (分時系統)

定義 : 在某一些地方(如: 恐龍本)會稱之為 Multitasking system,為 Mutiprogramming system 的一種,特色為 CPU 會很頻繁的進行 jobs switching,也就是在多個 Process 之間不斷的切換,這樣的設計適合與使用者進行交互,因為響應時間較短。作業系統會通過資源分享,讓每一個使用者有專屬的系統。

Mutiprocessors System (多核心系統)

定義 : 又被稱為 Multiprocessing, Parallel, Tighty-couple system 主要功能如字面上的意思,有多顆 CPU,或是多核 CPU,每一個核心 (core) 之間共享記憶體,I/O 裝置,匯流排等等。

Distributed System (分散式系統)

定義 : 又稱為 Loosely coupled system,特色為每一台電腦都是獨立的,有各自的 CPU, I/O 裝置,但是在軟體上會看作是一台電腦,像是Peer-to-peer (BT 的那個 P2P)

Real Time System (即時系統)

定義 : 對於每一個工作完成的時間有嚴格的要求,如果工作不能在規定的時間內完成,則視為失敗。

Reference

riscv riscv-fast-interrupt
chromitem-soc.readthedocs
RISC-V异常与中断机制概述
RISC-V spec references the word 'hart'
Serial communication
Linux 核心設計: Timer 及其管理機制


上一篇
Day-00 系列文簡介
下一篇
Day-02 xv6 RISC-V 概要
系列文
與作業系統的第一類接觸 : 探索 xv631
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言