作業系統介面

函式庫呼叫 vs 系統呼叫(library call vs system call)

想像你在工作中可能尋求的兩種協助。有些問題隔壁桌的同事不必離開房間就能立刻回答——那很快、就在本地、沒什麼大不了。另一些問題則需要有人實際走到一棟有門禁的大樓、刷卡進去、做完事再回來——較慢,而且要跨越一道有人看守的邊界。函式庫呼叫就像隔壁桌的同事;系統呼叫則像去那棟有門禁的大樓走一趟。

函式庫呼叫是呼叫一個住在使用者空間、被連結進你程式的函式庫裡的函式——C 標準函式庫、數學函式庫、或你自己的輔助函式。它在使用者模式下執行,與你其餘的程式碼處於同一個特權層級,不跨越任何保護邊界;就機制而言,它不過是你行程內部的一次跳躍與返回。相對地,系統呼叫是對核心的一個請求:它跨越使用者/核心邊界陷入核心、切換特權模式、執行可信的核心程式碼、再切回來。令人困惑的是,許多函式庫呼叫和許多系統呼叫的 C 語法看起來很像——你用同樣方式寫 strlen(s) 和 read(fd, buf, n)——所以這個區別在原始碼裡看不出來。差別在於工作發生在哪裡、以及是否跨越了那道特權之牆。

為何重要:這個區別同時驅動效能與正確性的推理。一個停在使用者模式裡的函式庫呼叫很便宜;一個最終會進行系統呼叫的呼叫則要付出跨越邊界的成本。它也影響你怎麼除錯:ltrace 顯示函式庫呼叫,而 strace 顯示系統呼叫;單一個函式庫呼叫如 fwrite(),可能因緩衝而觸發好幾次或零次系統呼叫。初學者常見的誤解是以為每個標準函式庫函式都「會去找作業系統」——多數並不會;只有需要特權操作的那些才會跨過去。

strlen(s) 是純函式庫呼叫——它在記憶體裡數字元,從不進入核心。write(1, s, n) 是系統呼叫——它陷入核心把位元組送到標準輸出。fputs(s, stdout) 是函式庫呼叫,它可能先把你的文字緩衝起來,之後才進行一次 write() 系統呼叫。

同樣的 C 語法、截然不同的機制:只有部分呼叫會跨進核心。

光看原始碼無法判斷一個函式是函式庫呼叫還是系統呼叫——那取決於函式內部做了什麼。可靠的辨識方式是工具(strace 對 ltrace)與文件,而不是呼叫的寫法。

又稱
library function vs syscall函式庫函式 vs 系統呼叫