„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Laufzeiten verstehen: Von C zu modernen Sprachen

Laufzeiten verstehen: Von C zu modernen Sprachen

Veröffentlicht am 08.11.2024
Durchsuche:338

Understanding Runtimes: From C to Modern Languages

Im Zeitalter der modernen Softwareentwicklung und -programmierung kann der Begriff „Laufzeit“ je nach Kontext und diskutierter Sprache unterschiedliche Bedeutungen haben. Ich bin hier, um diese Unterschiede zu verdeutlichen, und konzentriere mich dabei auf die Funktionsweise von Laufzeiten in C im Vergleich zu moderneren Sprachen wie Java oder Python. Ich beabsichtige, diesen Artikel auf Programmieranfänger zu konzentrieren, damit ich mich nicht mit komplexen Konzepten befasse.

Was ist eine Laufzeit?

Im Kern ist eine Laufzeit ein Programm selbst, das von einem Entwickler geschriebenen Code liest und ausführt. Es wird jedoch verwirrend, wenn einige Entwickler die Laufzeit mit der C-Sprache verwenden.

Moderne Sprachlaufzeiten

In Sprachen wie Java oder Python ist die Laufzeit ein Programm selbst, das Ihre myfile.js-Datei liest. Deshalb führen Sie nodejs-Programme aus wie: node myfile.js und v8 engine( ist die JavaScript-Engine, sie analysiert und führt JavaScript aus Code.) verwaltet alles dafür, ob Sie eine neue Datei erstellen, einen untergeordneten Prozess starten usw. und was am wichtigsten ist, Sie können nichts tun, was Ihnen Version 8 nicht erlaubt.
Aber wenn Sie ein C-Programm ausführen, führen Sie c myfile.c nicht aus, Sie müssen es nur einmal kompilieren und jetzt benötigen Sie kein gcc mehr, sondern führen es einfach direkt aus.

Die C-„Laufzeit“

In C gibt es kein separates Programm, das neben Ihrem Code ausgeführt wird, so wie in Java oder Python. Stattdessen handelt es sich bei dem, was oft als C-„Laufzeit“ bezeichnet wird, tatsächlich um einen Satz statisch eingefügten Codes und Anweisungen, die während der Kompilierung hinzugefügt werden. Es handelt sich um einen minimalen Satz von Anweisungen, die in der endgültigen Binärdatei enthalten sind, um bestimmte notwendige Aufgaben auf CPU-/Betriebssystemebene zu erledigen. Es übernimmt die Erstellung und Demontage von Stack-Frames für Funktionsaufrufe (unter Verwendung von Anweisungen wie PUSH, POP, CALL, RET in Assembly). Selbst dies kann überschrieben werden, indem Sie Ihre eigene __start-Funktion mithilfe von Inline-Assembly bereitstellen, wodurch Entwickler vollständige Kontrolle über den Einstiegspunkt und die Initialisierung des Programms haben.


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
}


Das sieht überhaupt nicht nach Laufzeit aus, es ist nur ein vom Compiler hinzugefügter Assembler-Code, sodass Entwickler das nicht tun müssen.

Die Macht und Verantwortung von C

In C können Sie Systemaufrufe direkt über Inline-Assembly aufrufen, um mit dem Kernel auf eine Weise zu interagieren, die das Betriebssystem normalerweise nicht zulässt. Auf diese Weise werden Malware erstellt. Mit der Inline-Assembly können Entwickler Assembler-Anweisungen innerhalb von C-Code schreiben. Dies wird häufig für leistungskritischen Code oder für den Zugriff auf bestimmte Hardwarefunktionen verwendet.

Inline-Montage in C

  • Inline-Assembly ermöglicht Entwicklern das Schreiben von Assembler-Anweisungen innerhalb von C-Code. Dies wird häufig für leistungskritischen Code oder für den Zugriff auf bestimmte Hardwarefunktionen verwendet.
  • Es bietet eine Möglichkeit, CPU-Anweisungen direkt auszuführen.

Direkte Interaktion mit dem Kernel

  • Mithilfe der Inline-Assembly kann ein Programmierer Systemaufrufe direkt aufrufen, ohne über Bibliotheken höherer Ebenen gehen zu müssen.
  • Zum Beispiel können wir Inline-Assembly verwenden, um Register mit den entsprechenden Parametern für einen Systemaufruf einzurichten und diesen dann auszulösen.
  • Da die Inline-Assemblierung eine Kontrolle über Systemressourcen auf niedriger Ebene ermöglicht, kann sie verwendet werden, um Sicherheitsmechanismen zu umgehen oder den Kernel direkt zu manipulieren. Auf diese Weise kann Schadsoftware unbefugte Aktionen ausführen, beispielsweise auf geschützten Speicher zugreifen, Systemaufrufe abfangen oder Prozesse und deren Speicher manipulieren.
  • Malware kann Schwachstellen im Betriebssystem ausnutzen oder diese Interaktionen auf niedriger Ebene nutzen, um Aufgaben wie Keylogging, Rechteausweitung oder Stealth-Operationen auszuführen.

Unter Linux verfügt C über ein FLAG, mit dem Sie Dateidaten direkt auf ein Speichergerät schreiben können und dabei einige der Caching-Mechanismen des Kernels umgehen. Es heißt O_DIRECT-Flag und wird in Kombination mit den Systemaufrufen open und write verwendet. Dieses Flag stellt sicher, dass Daten nicht im RAM gepuffert oder vom Kernel im Kernelraum verwaltet werden. Dadurch werden die Daten direkt auf die Festplatte geschrieben. JVM lässt dies nicht zu, und das ist nur ein einfaches Beispiel.
Hier ist ein einfaches Beispiel:


asm volatile (
"syscall"
: "=a" (written)
: "0" (1),
"D" (fd),
"S" (buffer),
"d" (BLOCK_SIZE)
: "rcx", "r11", "memory"
);


*Hinweis: * (geschrieben) ist eine in main() erstellte Variable, (1) ist die Systemaufrufnummer für das Schreiben, (fd) ist der Ort, an dem die Datei geschrieben wird, d. h. int fs = open("path .log",O_WRONLY; (BLOCK_SIZE) ist ein weiterer Variablenname. Er ist komplexer.

Die Entwicklung der Laufzeiten

Es ist wichtig zu verstehen, dass sich das Konzept der Laufzeit im Laufe der Jahre weiterentwickelt hat. Die C-„Laufzeit“ der 70er Jahre unterscheidet sich stark von den robusten Laufzeitumgebungen, die wir in Sprachen aus den 2000er Jahren sehen. Diese Entwicklung kann bei der Diskussion von Laufzeiten zu Verwirrung führen, insbesondere zwischen Entwicklern, die mit verschiedenen Programmierepochen vertraut sind.

Abschluss

Ich denke, die Leute vergleichen jetzt die Laufzeiten der 1970er-Jahre mit den Laufzeiten der 2000er-Jahre, was dazu führt, dass neue Entwickler mit alten Entwicklern verwechselt werden.
Ein bestimmtes Problem zu lösen ist die Hauptaufgabe jeder Programmiersprache. Sie möchten kein ganzes Framework zum Erstellen von APIs in C schreiben. Wir haben NodeJS und es ist gut darin, und Sie müssen keinen Bare-Metal-Code in Javascript schreiben, weil wir Ich habe bereits C und es ist großartig darin. Warum das Rad neu erfinden, lasst uns die Räder nutzen und ein fantastisches Auto erschaffen, es sei denn, Sie möchten es nicht auf dem Mars fahren.

Freigabeerklärung Dieser Artikel ist reproduziert unter: https://dev.to/bossysmaxx/understanding-runtimes-from-c-to-modern-linguals-3fkj?1 ​​​​​​Bei Verstößen wenden Sie sich bitte an [email protected], um ihn zu löschen Es
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3