我問這個問題,是因為我得到了關于系統呼叫的非常矛盾的定義。
一方面,我看到的定義是它們是作業系統提供的 API,用戶程式可以呼叫。由于這個 API 是一個高級介面,所以它必須用 C 等高級語言來實作。
另一方面,我看到實際的作業系統系統呼叫是機器指令,對于這些指令,你必須設定某些暫存器來呼叫(根據作業系統設定的一些合規標準)。但這看起來與 UNIX 的 API(如 open()、write()和 read())完全不同,那么這里到底發生了什么?
我還讀到,這些高級介面是在C庫中實作的,而C庫則進行實際的匯編代碼系統呼叫。在這種情況下,為什么我們說作業系統提供了這個介面,而它實際上是由C語言提供的。如果我想直接對作業系統進行UNIX系統呼叫,而不需要使用C語言,該怎么辦?
uj5u.com熱心網友回復:
有兩個open函式--一個是由作業系統(如Linux)暴露的系統呼叫open,二是由C標準庫(如glibc)暴露的C-library函式open。
你可以看到這些函式的兩個不同的手冊頁--運行man 2 open來查看關于系統呼叫的手冊頁,而man 3 open來查看關于C標準函式的手冊頁。
你提到的
open、write和read等函式可能會引起混淆 - 因為它們既作為系統呼叫又作為C標準函式存在。但它們完全是獨立的物體 - 事實上,glibc 的 open 函式 甚至沒有使用 open 系統呼叫 - 它使用 openat 系統呼叫。
在 Windows 上,系統呼叫 open 甚至不存在 - C 標準庫函式 open 確實 仍然存在,并且在幕后使用 WinAPI 的 CreateFile。
如果我想直接對作業系統執行 UNIX 系統呼叫,而不必使用 C 語言呢? 而不必使用 C?
這是有可能的--事實上,glibc必須這樣做以實作C語言標準庫函式。但是這很棘手,需要為系統呼叫實作包裝器,有時甚至需要手工制作匯編。
如果你想親自看看,你可以看看glibc如何實作open:
int
__libc_open (const char *file, int oflag, ...)
{
int mode = 0;
if (__OPEN_NEEDS_MODE (oflag))
{
va_list arg;
va_start (arg, oflag);
mode = va_arg (arg, int)。
va_end (arg);
}
return SYSCALL_CANCEL (openat, AT_FDCWD, file, oflag, mode) 。
}
...
weak_alias (__libc_open, open)
注意,該函式以呼叫宏SYSCALL_CANCEL結束,這將最終呼叫作業系統暴露的openat系統呼叫。
uj5u.com熱心網友回復:
作業系統庫是用匯編還是用C撰寫的
這是一個無法真正回答的問題,因為它取決于。從技術上講,對實作沒有任何限制(也就是說,它可以用任何語言撰寫,盡管C語言可能是最常見的,其次是匯編)。
這里的重要部分是ABI。它定義了如何進行作業系統呼叫。
你可以進行系統呼叫。
您可以在匯編中進行系統呼叫(如果您知道 ABI,您可以手動撰寫所有代碼來遵守),C 編譯器知道 ABI 并將自動生成進行呼叫所需的所有代碼。
盡管大多數語言都允許您進行系統呼叫,但它們要么知道 ABI,要么有一個封裝 API,可以將語言呼叫轉換為適合該作業系統的 ABI。
我這樣問,是因為我得到的系統呼叫的定義非常矛盾。
這些定義將取決于背景關系。你必須舉例說明這些定義是什么和在什么情況下被使用。
一方面,我看到的定義是它們是作業系統提供的API,用戶程式可以呼叫。
當然,這是看待它的一種方式。
更嚴格地說,我認為作業系統提供了一組可用于執行特權任務的介面。現在,這些介面可以通過特定環境提供的 API 暴露出來,使其更容易使用。
由于該 API 是一個高級介面,因此必須用 C 等高級語言來實作。
某種程度上是真的。
一個環境可以暴露一個 API 并不意味著它需要一種高級語言(而 C 不是一種高級語言,它比匯編高一級,被認為是一種低級語言)。而且,僅僅因為它是由語言暴露出來的,并不意味著它是用該語言實作的。
另一方面,我看到實際的作業系統系統呼叫是機器指令,對于這些指令,你必須設定某些暫存器來呼叫(根據作業系統設定的一些合規標準)。
好的。在這里,我們已經從系統呼叫轉移到系統呼叫。我們應該非常注意如何使用這些術語,以確保我們沒有混淆不同的術語。
我將(這仍然有點抽象)把計算機看作是幾個層次的抽象:
硬體
------ --------------
系統呼叫
作業系統 --------------
系統 呼叫 (讀/寫等)
------ --------------
語言 界面 (讀/寫等)
如果你想的話,你可以直接探測硬體(如果你知道怎么做),但如果你能進行系統呼叫(如果你知道怎么做),那就更好了,但最好使用作業系統的系統呼叫,它使用定義好的ABI,但最好使用語言介面(你稱之為API)來呼叫底層系統呼叫。
但這看起來與 UNIX 的 API(如 open()、write()和 read())完全不同,那么這里到底發生了什么。
在這里,UNIX 作業系統提供了打開/關閉/讀取介面。
C 庫在作業系統的系統呼叫之上提供了一個非常薄的 API 封裝介面。然后,C 編譯器將生成正確的指令,以使用正確的 ABI 來呼叫系統呼叫,這反過來又將呼叫作業系統的下一層來使用系統呼叫。
我還讀到,這些高級介面是在C庫中實作的,而C庫則負責實際的匯編代碼系統呼叫。
高級介面可以用任何語言撰寫。但是,C語言是如此容易使用,以至于大多數其他語言都懶得自己做,而只是通過C語言的介面來呼叫。
uj5u.com熱心網友回復:
直接用匯撰寫東西是非常罕見的。通過用C語言撰寫,你可以為許多不同的CPU架構進行編譯,而用匯編撰寫,你基本上只能用一個特定的架構。大多數作業系統都是用C語言撰寫的。我們說作業系統提供了介面,因為你正在與作業系統進行互動,而作業系統恰好是用C語言撰寫的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/318326.html
標籤:
下一篇:獲取每月同一天的日期
