在現代軟體開發和程式設計時代,術語「運行時」可能具有不同的含義,具體取決於上下文和所討論的語言。我在這裡澄清這些差異,重點關注與 Java 或 Python 等更現代的語言相比,C 語言的運行時如何運作。我打算讓這篇文章專注於初學者程式設計師,因此我將避免深入研究複雜的概念。
從本質上講,運行時是一個程式本身,它讀取並執行開發人員編寫的程式碼。但當一些開發人員使用 C 語言運行時,就會變得混亂。
在Java 或Python 等語言中,運行時本身就是一個讀取myfile.js 檔案的程序,這就是為什麼您運行Nodejs 程序,例如:node myfile.js 和v8 引擎(是JavaScript 引擎,它解析並執行JavaScript程式碼。
但是當你執行一個c程式時,你不需要執行c myfile.c,你只需要編譯一次,現在你不再需要gcc了,直接執行它。
在 C 中,沒有像 Java 或 Python 那樣與程式碼一起運行的單獨程式。相反,通常所說的C“運行時”實際上是在編譯期間添加的一組靜態插入的程式碼和指令。它是最終二進位檔案中包含的最小指令集,用於處理 CPU/作業系統層級的某些必要任務。它處理函數呼叫的堆疊幀創建和拆卸(在彙編中使用 PUSH、POP、CALL、RET 等指令)。即使這一點也可以透過使用內聯彙編提供您自己的 __start 函數來覆蓋,從而使開發人員能夠完全控製程式的入口點和初始化。
void __start() { // Custom entry point, no standard library initialization // You have no access to argc and argv here unless you access them manually from registers // you can create you own custom stack setup, initialization and etc here. // Exit directly using a syscall asm("mov $60, %rax; mov $0, %rdi; syscall"); // exit(0) syscall }
這看起來根本不像運行時,它只是編譯器添加的一些彙編語言程式碼,因此開發人員不必這樣做。
在 C 語言中,您可以使用內聯彙編直接調用系統調用,以作業系統通常不允許的方式與內核交互,這就是惡意軟體的創建方式。內聯彙編允許開發人員在 C 程式碼中編寫彙編語言指令。這通常用於性能關鍵的程式碼或存取特定的硬體功能。
在linux C中有一個FLAG,允許您直接將檔案資料寫入儲存設備,繞過一些核心的快取機制,稱為O_DIRECT標誌,它與open和write系統呼叫結合使用。此標誌確保資料不會在 RAM 中緩衝或由核心在內核空間中管理,這會直接將資料寫入硬碟,JVM 不允許您這樣做,這只是一個簡單的範例。
這是一個簡單的例子:
asm volatile ( "syscall" : "=a" (written) : "0" (1), "D" (fd), "S" (buffer), "d" (BLOCK_SIZE) : "rcx", "r11", "memory" );
*注意:*(寫入)是在main() 內部建立的變量,(1) 是寫入的系統呼叫號,(fd) 是檔案將被寫入的位置,即int fs = open("path .log",O_WRONLY; (BLOCK_SIZE) 是另一個變數名稱。它比那個更複雜。
了解運行時概念多年來的演變非常重要。 70 年代的 C「運行時」與我們在 2000 年代的語言中看到的健壯的運行時環境有很大不同。在討論運行時時,這種演變可能會導致混亂,尤其是在熟悉不同程式設計時代的開發人員之間。
我認為人們現在正在將 1970 年代的運行時與 2000 年代的運行時進行比較,這讓新開發人員與老開發人員感到困惑。
解決特定問題是任何程式語言的主要任務,你不想用C 編寫一個完整的框架來創建API,我們有NodeJS,它很擅長,你不需要用JavaScript 編寫裸機程式碼,因為我們已經有了C 並且它在這方面非常棒。為什麼要重新發明輪子,讓我們用輪子創造一輛神奇的汽車,除非你不想在火星上駕駛它。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3