--- title: 'Linux 系統 - 模式 & System call' disqus: kyleAlien --- Linux 系統 - 模式 & System call === ## OverView of Content 使用到指令 cc(編譯 c)、strace(System call 追蹤)、sar(系訊訊息)、**ldd(查看分享庫依賴)**、kill ... [TOC] ## 電腦系統概念 電腦是不斷處理以下幾個步驟 1. 透過輸入裝置 or 網路命令,**委託電腦進行處理**,並將這些指令存在 **記憶體中** 2. 要求 CPU 運算記憶體中的委託命令 3. 將 CPU 計算的結果寫入記憶體 4. 將記憶體上的資料寫入硬碟中 or 透過網路傳至別的電腦 >  ### 程式分類 1. 分類 | 種類 | 說明 | 舉例 | | -------- | -------- | -------- | | 應用程式 | 直接協助使用者 | Office、APP | | 中介軟體 | 多數應用共通處理,可以算是協助開發的 Library | Web 伺服器、資料庫 | | OS 系統 | 直接操作硬體 (韌體的部分) | Linux、Mac、Windows | >  2. 多行程協作 >  ### 程式組成 - Process * 程式的運行最小單位為 Process 行程 (也就是進程),^1^ 程式使用的進程可以是複數 or 單數,^2^ **不同進程之間也可以通訊** >  ### Linux 驅動裝置 - 概述 * 上面有說到 Linux 會透過驅動裝置進行存取,而 Linux 有特定的規定,必須透過 **==核心模式==才能存取裝置** >  ## 操作系統 os 操作系統簡單來說就是介於硬體 & 應用之間的東西,**向下負責硬體,向上負責提供高效的 API,可說是 ==硬件管家==** >  ### OS 作用 * 以 Linux 來說,Linux 的特色之一是外部裝置驅動 1. 如果沒有 OS 的話,每個應用就必須針對各個裝置寫必要的驅動程式 >  2. 有 OS 的話,以 Linux 來說就有共用的裝置驅動程式來做處理 (相當於一個共用的 Lib) >  ### OS 分類 | 分類角度 | Example | | -------- | -------- | | 應用領域 | 嵌入式系統、桌面操作、服務器類型 | | 用戶數量 | 單用戶:Dos; 多用戶:window, mac, unix | | 實時性(多線程) | 實時操作系統:RTOS、VRTX; 分時操作系統:window, mac, unix| | 指令長度 | 8、16、32、64 bit | | 分佈性 | 分佈式、網路式 | | open source | 開源:Android, Unix; 閉源:Mac、Window | | Unix 系列 | Unix-like:Linux, Mac, Xinu; Non-Unix-like:Windows | | POSIX 兼容性 | Linux 兼容 | ### Android 系統 * **Android os 是基於 Linux Kernel 的**,會使用的原因如下: 1. 進程、記憶體管理 2. 權限安全機制 3. 經過驗證的驅動程序模型 4. 提供多種共享厙 5. Open Source~ ### 資料 & 裝置 - 關係 * 簡單來說資料與裝置的關係如下 1. 資料透過讀取硬體 2. 再將資料儲存到記憶體 3. 最後到 CPU 做運算 4. 將結果存到記憶體 5. 最後存到裝置 or 網路上 >  ### 記憶體速度 & 價格 & 大小 | 記憶體分類 | 速度 | 價格 | 大小 | | -------- | -------- | -------- | -------- | | Register | 最快 | 最貴 | 最小 | | SDR (靜態、快速記憶體) | 中 | 中 | 中 | | DDR (動態記憶體) | 最慢 | 最便宜 | 最大 | * 雖然 DDR 是記憶體中速度最慢的,但仍比硬碟快得多 ~ >  ## 核心模式 & 使用者模式 * Linux 透過 **++硬體++ 的協助,讓行程無法對裝置逕行存取**,**CPU 具備 `核心模式` & `使用者模式` 兩種**,除了 `Linux 驅動裝置` 需透過核心存取外,其他還有 `Process 管理系統`、`Process 排程器`、`Memory 管理系統` * **核心模式**:以核心模式來運作、OS 核心處理的稱為核心 (kernel),它主要管理系統 CPU、Memory (核心有核心專用的 CPU、Memory 區塊,這裡先不說明) >  ### System Call - 核心模式 * System Call 是一種統稱 (許多行為都可以稱為 System Call),以下舉例幾個 :::success * 當使用到 System call 時就一定會切換到核心模式 ::: 1. 建立、刪除 Process 2. 確保 (申請)、釋放 Memory 3. 不同行程之間的通訊 (mmap) 4. 網路 5. 檔案系統操作 6. 檔案操作 (裝置 IO 存取) ### CPU 中斷 - 模式轉換 * 當使用者有 **使用到 System call 的動作時,便會觸發 CPU 產生 ==中斷事件==,產生中斷事件時 CPU 就換轉換到 ++核心模式++**,並檢查 System call 要求是否正常 > CPU 收動 System call 中斷事件後會先檢查,eg. 檢查記憶體段是否要求正常 (是否超出 or 不合法) >  ### 追蹤 System Call - strace 命令 * 前面有說到 IO 存取會呼叫到 system call,以下就寫一個簡單的 c 語言程式進行 IO 存取 1. **前置作業**: 安裝必要套件 ```shell= # 先安裝 gcc 套件 sudo apt-get install -y gcc # 創建文件 touch hello.c # 編輯文件 vim hello.c ``` 2. 使用 puts 終端機上輸出 `Hello world!` ```c= #include <stdio.h> int main(void) { puts("Hello world!"); return 0; } ``` 3. 使用 gcc 編譯 hello.c 檔案 ```shell= # 編譯 & 輸出可執行檔 cc -o hello hello.c ``` 4. 運行編譯結果 ```shell= # 運行 ./hello ``` >  * **使用 `strace` 命令** 追蹤 system call 相關資訊 >  ```shell= # -o 另外輸出一個檔案 strace -o hello.log ./hello # 查看 system call 數量 wc -l hello.log # -n 輸出行數 cat -n hello.log ``` 重點是第 28 行的 write ~ >  * 同樣使用 strace 命令,追蹤 Python 程式試試看,可以看到 python 使用到了 400 多行 system call (因為 Python 包裝較多層) ```shell= # echo 輸出,並重新導向,最終輸出 hello.py echo 'print("Hello world, by py")' > hello.py | cat hello.py # 執行 python3 python3 hello.py # 同上 strace -o hello.py.log python3 hello.py # 同上 cat -n hello.py.log ``` 雖然使用到 400 多次 system call,但最終仍都會用到 write ~ >  ### 測試 System call & CPU 模式 - sar 收集系統資訊 * sar 命令是用來收集系統資訊 1. sar 使用格式 ```shell= # -P 是行程 # ALL 是全部 CPU # 1 是一秒一次 # 10 是監看次數 sar -P ALL 10 ``` 2. 使用者、核心模式 看法 | 模式 | 關注欄位 | | -------- | -------- | | 使用者 | `%user` + `%nice` | | 核心 | `%system` | >  * 以下做兩個 loop 實驗,使用無限迴圈執行 ^1^ 沒有任何動作的執行檔案,^2^ 執行不斷 system call,並觀察 sar 數據 1. 沒有任何動作的執行檔案 (檔案創建、編輯指令都先略過,需要可以參考上面的) ```c= // loop.c int main(void) { for(;;) ; } ``` * 背景執行 + 監聽 CPU,最終會發現 **loop.c 都是 (觀察 user + nice) 運行在使用者模式** ```shell= # 編譯檔案 cc -o loop loop.c # 背景執行 loop (使用 & 就是背景執行,並且它會返回 PID,方便我們 Kill) ./loop & # 監聽 CPU sar -P ALL 1 ``` >  * **CPU 概念**:單執行 for 迴圈時 (基本上都消耗在 `%user` 欄位) >  2. 執行不斷 system call,`getppid` 函數 (取的當前行程的 pid) ```c= // ppid_loop.c #include <sys/types.h> #include <unistd.h> int main(void) { for(;;) getppid(); } ``` * 背景執行應用 (`ppid_loop.c`) + 監聽 CPU,最終會發現 **ppid_loop.c 分別有使用者 + 核心模式** ```shell= # 編譯檔案 cc -o ppid_loop ppid_loop.c # 背景執行 loop (使用 & 就是背景執行,並且它會返回 PID,方便我們 Kill) ./ppid_loop & # 監聽 CPU sar -P ALL 1 ``` >  * **CPU 概念**:因為有使用 SystemCall 函數,所以 CPU 消耗會分配部分到 `%system` >  :::success * 最後移除背景運行行程 ```shell= # pid 在 & 之後返回 kill <pid> ``` ::: ### System call 耗時 * strace -T 用來採集各種 System call 的耗時,以 **微秒 (µs) 為單位**,以下運行 ./hello 執行檔案,並監測它輸出 write 的耗時 ```shell= strace -T ./hello ``` 可以看到該裝置運行時耗費了 120 µs 來執行 write 的 System call >  ## System call 包裝函數 Linux 由提供許多 CPU 架構的 library,**System call 無法由 C 語言這種高等語言來呼叫,必須要使用到與 CPU 架構對應的 ==組合語言== 來進行呼叫** ### OS 包裝 System call * 像是 Linux OS 會提供不同 CPU 架構使用的組合語言 (eg. `x86`、`x86_64`、`arm7`... 等等),如果沒有 OS 的話每個行程就要撰寫對應的 CPU 組語 ```java= // 以 x86_64 為例的組語範例 mov $0x6e,%eax // 將 0x6ax 寫入 eax 暫存器 syscall // 對 cpu 發出 system call,cpu 收到後產生中斷,並進入 ++核心模式++ ``` >  ### 標準 C Library - glibc * C 語言有依照 ISO 訂製的標準函數 Library,Linux 也有提供 C 的標準,通常依照 GUN 專案所以提供的 **glibc** 作為標準 C 函數 Library,幾乎所以有的 C 語言程式都會連接到 glibc * 該程式與何種 library 相連可以使用 `ldd` 命令查看 :::info * ldd : print shared object dependencies ldd 後面是添加 **執行檔** 的絕對路徑 ::: * 以下幾個範例都連接到 `libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6` 也就是 glic 1. 查看 echo ```shell= # 查看 echo 命令位置 which echo # ldd 後面要添加絕對路徑 ldd /usr/bin/echo ``` >  2. 查看自己寫的 hello 執行檔 ```shell= # ldd 後面要添加絕對路徑 ldd hello ``` >  3. 查看 python3 ```shell= # 查看 python3 命令位置 which python3 # ldd 後面要添加絕對路徑 ldd /usr/bin/python3 ``` >  ### OS 提供程式 * 以下提幾個常見到的程式 | OS 程式 | 關鍵字 | | -------- | -------- | | 系統初始化 | init | | 變更 OS 行動 | sysctl、nice、sync | | 檔案操作 | touch、mkdir | | 文字加工 | grep、sort、uniq | | 效能測量 | sar、iostat | | 編譯器 | gcc | | 腳本語言執行環境 | perl、python、ruby | | shell | bash | | 視窗系統 | X | ## Appendix & FAQ :::info ::: ###### tags: `Linux 系統核心`
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.