Warum werden UNIX-Dateideskriptoren nicht durch ihren eigenen Typ implementiert, insbesondere in C++? [closed]

Lesezeit: 8 Minuten

Benutzer-Avatar
Allicoder

Ich habe in letzter Zeit eine ganze Menge Dateideskriptoren verwendet und mich gefragt, warum sie als Ganzzahlen implementiert sind?

Das bedeutet, dass sie leicht mit anderen ganzen Zahlen verwechselt werden können, und es gibt keine Möglichkeit, ohne Kontext zu wissen, was sie sind, worauf sie zeigen, ob sie offen sind usw.

In C, FILE ist undurchsichtig struct Typ. Viele Leute auch typedef z.B status_t als ganze Zahl, so dass ihre Funktion offensichtlich ist. Es scheint das Beste zu sein, sie entweder als undurchsichtigen Typ oder (z. B. in C++) als Klasse zu implementieren, die einen Teil der Implementierung übernehmen und auch aufräumen kann namespace ein bisschen (ein Anruf bei pipe() oder open() scheint so harmlos, und es ist nicht offensichtlich, was Sie ohne Kontext pfeifen oder öffnen). Wie zB std::file_descriptormit Konstruktoren/Factory-Funktionen zum Erstellen von Pipes oder Öffnen von Dateien und so weiter.

Ich hoffe, das gehört zum Thema dieser Seite; Ich habe versucht, es so zu formulieren: “Warum wurde gerade diese Entscheidung getroffen?„Falls jemand weiß, wo es besser passt, bitte melden.

  • Wieso den? Weil POSIX keine C++-spezifische API definiert.

    – R.Martinho Fernandes

    22. Juli 2013 um 13:13 Uhr


  • Meinst du: Warum definiert C++ die C-API nicht mit einer Typedefoder Warum verwendet die C-API überhaupt keine Typedef??

    – Nicht zu gebrauchen

    22. Juli 2013 um 13:14 Uhr

  • Dateideskriptoren müssen universell sein, ints sind so ziemlich universell, wie man es für Datentypen bekommen kann.

    – Daniel Gratz

    22. Juli 2013 um 13:17 Uhr

  • Weder C noch C++ haben einen definierten Dateideskriptor; Es ist POSIX, das dieses Konzept derzeit standardisiert (und es kann übrigens auf jedem bestimmten Betriebssystem existieren oder nicht).

    – PlasmaHH

    22. Juli 2013 um 13:40 Uhr

  • @FrankH. Außer dass, als es repariert wurde, int war nur 16 Bit (und die interne Implementierung beschränkte es auf 19 Dateien).

    – James Kanze

    22. Juli 2013 um 14:14 Uhr

Benutzer-Avatar
James Kanze

Geschichte, sonst nichts. In den 1970er Jahren schien es wahrscheinlich kein Problem zu sein, es einfach zu verwenden int (und der Wert war tatsächlich ein Index in eine Tabelle mit fester Größe). Eine spätere Änderung in einen anderen Typ hätte den Code beschädigt.

  • Und es scheint immer noch kein Problem zu sein 🙂

    Benutzer405725

    22. Juli 2013 um 13:36 Uhr

  • @VladLazarenko Es stimmt, dass ich mich nicht erinnern kann, jemals einen Fehler gesehen zu haben, weil jemand so etwas getan hat ++fdnur weil fd war ein int.

    – James Kanze

    22. Juli 2013 um 14:13 Uhr

  • @JamesKanze – Ich habe. Es war eine Funktion “Alle offenen Dateideskriptoren schließen”, die über eine begrenzte Anzahl von Dateideskriptoren iterierte. Jemand entschied, dass, da es eine Ressource gab, die auf die Anzahl der Dateideskriptoren begrenzt war, hey, der maximal mögliche Dateideskriptor auf MAX_INT geändert werden sollte. Was kann daran schiefgehen?!?

    – Julie in Austin

    3. Mai 2019 um 20:48 Uhr

Benutzer-Avatar
Shahbaz

Ihre Frage lässt sich zweiteilen:

Warum ist der POSIX-Dateideskriptor int?

Wie bei den meisten Dingen in bereits etablierten Tools und Bibliotheken ist die Antwort wahrscheinlich historisch bedingt. Die Antwort von James weist darauf hin.

Es ist wahrscheinlich eine gute Idee, den Dateideskriptor undurchsichtig zu machen, aber nicht aus dem von Ihnen genannten Grund. Den Typ undurchsichtig zu machen, ist gut, um basierend auf einigen Parametern einen anderen Typ zu haben. Auf einigen Systemen möchten Sie beispielsweise a long long als Dateideskriptor. Wie es jedoch scheint, hat niemand nirgendwo 2 Milliarden offene Dateien gleichzeitig benötigt und daher hat sich niemand darum gekümmert, dieses nicht vorhandene Problem zu beheben.

Andererseits so etwas wie typedef int file_descriptor; behebt keines der oben genannten Probleme:

Es bedeutet, dass sie leicht mit anderen ganzen Zahlen verwechselt werden können …

Wenn Sie Ihre Variablen verwechseln, habe ich schlechte Nachrichten für Sie. Der Compiler hilft Ihnen da auch nicht weiter file_descriptor und int vom gleichen Typ sind, also ist jede Operation auf dem einen auf dem anderen erlaubt.

… und es gibt keine Möglichkeit, ohne Kontext zu wissen, was sie sind, worauf sie hinweisen, ob sie offen sind usw.

Das kannst du nicht mit FILE entweder. Deshalb haben Sie Funktionen, die die gesuchten Informationen abfragen und zurückgeben, genau wie bei FILE. typedefWenn Sie den Typ angeben, erhalten Sie keine zusätzlichen Informationen.

Warum hat POSIX keinen C++-Wrapper dafür?

Kurz gesagt, weil außer Microsoft kein Betriebssystementwickler in C++ verliebt ist. Windows ist kaum noch POSIX, daher gibt es für Microsoft keine Hoffnung, irgendetwas an POSIX zu verbessern. Andere Betriebssysteme, die POSIX-konform sind, haben eine C-API als De-facto-Systemprogrammiersprache (teilweise, weil, wie nm sagt, fast alle Sprachen an C binden können).

Tatsächlich ist C++ bei Anwendungsentwicklern beliebt, aber nicht so sehr bei Systemprogrammierern. Auch das POSIX-Komitee scheint sich nicht besonders für C++ zu interessieren. Aus diesem Grund würden Sie C- und nur C-Lösungen und Argumente in Bezug auf die POSIX-API sehen. Beachte das auch POSIX wurde geschaffen, um insbesondere die Schnittstelle von UNIX zu standardisierendas in C und einem seiner wichtigsten Abkömmlinge, Linux, geschrieben wurde, ist ebenfalls stark an C gebunden.

  • Ein weiterer Punkt: Als UNIX entwickelt wurde, gab es noch kein C++. Bjarne war zu dieser Zeit in Europa.

    – xis

    22. Juli 2013 um 15:43 Uhr

  • Die meisten Quellen sind sich einig, dass Java beliebter ist als C++. Warum sollte POSIX C++ vor Java unterstützen? (Das sollte es nicht; es definiert APIs so irgendein Sprache binden kann).

    – n. 1.8e9-wo-ist-meine-Aktie m.

    22. Juli 2013 um 16:24 Uhr

  • @nm Welche Quellen? Wenn ich mich umschaue, scheint Java außer in Webservern und kleinen eingebetteten Anwendungen in Smartphones fast dem Untergang geweiht zu sein. Und Java erstellt seine eigene Umgebung, unabhängig vom umgebenden Betriebssystem. Und soweit ich weiß, wird C aus historischen Gründen hauptsächlich in Linux-Kerneln verwendet. Mit Ausnahme von Linux sind die meisten neuen Linux-Entwicklungen in C++. (In der Begründung für pthread_cleanup_push/pthread_cleanup_popPosix gibt sogar an, dass die ideale Lösung Ausnahmen beinhalten würde – ein starker Hinweis darauf, dass sie C++ mögen würden.)

    – James Kanze

    22. Juli 2013 um 16:54 Uhr

  • Dieser Wikipedia-Artikel listet mehrere Umfragen zur Sprachpopularität auf, Google hat noch mehr. “Java erstellt seine eigene Umgebung” — jede Sprache tut dies bis zu einem gewissen Grad. C und C++ haben auch ihre sprachspezifischen I/O-Möglichkeiten, aber POSIX schreibt einen eigenen Satz vor. “C wird aus historischen Gründen hauptsächlich in Linux-Kerneln verwendet.” — Vielleicht hat es mit Linus zu tun Verachtung von C++ und C++ Programmierern. „ein starker Hinweis darauf, dass sie C++ mögen“ – oder vielleicht Objective C, wer weiß?

    – n. 1.8e9-wo-ist-meine-Aktie m.

    22. Juli 2013 um 17:23 Uhr

  • + zu netter Antwort für nettes Abzeichen. Das ist wirklich eine tolle Antwort. Ahaa, ich habe bemerkt, dass Sie promoviert sind! dass der Grund tiefe Kenntnisse.

    – Grijesh Chauhan

    22. Juli 2013 um 18:50 Uhr


Benutzer-Avatar
Kaz

Die Unix-Schnittstelle wird in Bezug auf die C-Sprache beschrieben, aber es ist ebenso wichtig, dass Systeme eine ABI haben, nicht nur eine API.

Ausgefallene Datenstrukturen, die für eine Programmiersprache spezifisch sind, erschweren die ABI. Auf der ABI-Ebene haben Sie nur Datentypen auf niedriger Ebene wie “32-Bit-Ganzzahl ohne Vorzeichen” und einfache Aggregate davon.

Davon abgesehen verwendet die Unix-Schnittstelle Typen wie pid_t und so weiter, warum also nicht eine dieser Typedefs für Dateideskriptoren?

Dateideskriptoren haben bestimmte wohlbekannte Werte, und wenn ein neuer Dateideskriptor geöffnet wird, wird immer der kleinste verfügbare positive Wert verwendet. Dateideskriptorwerte fungieren effektiv als Array-Indizes in einer Tabelle von Deskriptoren, und das Design ist absichtlich so. Das Modell des Programmierers von Dateideskriptoren ist, dass es eine Array-ähnliche Struktur von ihnen im Kernel gibt. Das dup2 Funktion kann tatsächlich einen Dateideskriptor von einem Steckplatz zum anderen duplizieren. Solche Array-Indizes könnten genauso gut sein intmit negativem Wert zur Signalisierung von Fehlern.

C-Typedefs kaufen keine zusätzliche Typprüfung, aber sie bringen ein wenig Lesbarkeit und auch Abstraktion: Unabhängigkeit von einem bestimmten Integer-Typ. EIN fd_t Typ könnte ein sein int auf einem System und a long übereinander. Aber seit int vor einigen Jahrzehnten fast allgegenwärtig 32 Bit breit geworden ist, besteht keine wirkliche Notwendigkeit, es zu abstrahieren, um es unter demselben Namen breiter machen zu können. Es ist sehr ungewöhnlich, dass ein Programm mehr als zwei Milliarden offene Dateideskriptoren benötigt.

Im Gegensatz dazu wäre es für Implementierer sehr unbequem, wenn eine Ebene int verwendet wurden, anstatt, sagen wir, pthread_t.

int Deskriptoren erwiesen sich für die Designer der Windows Socket API, die a erfanden, als schwer zu schlucken SOCKET typedef, dessen Werte nicht die niedrigsten verfügbaren positiven ganzen Zahlen sind; nur eine der Macken, die zu Portabilitätsärgern führen. Es gibt jedoch einen echten semantischen Unterschied darin, dass Code, der darauf angewiesen ist, dass diese Deskriptoren kleine Werte in einem Bereich sind, entweder nicht funktioniert oder sich ineffizient verhält.

Es gibt historische Fälle, in denen Unix überarbeitet wurde, um eine Ebene zu ersetzen int Typ mit einigen typedef. Zum Beispiel in einem accept Funktion war die Größe der entfernten Adressstruktur früher gerade int. Dann wurde es socklen_t. Es besteht keine technische Notwendigkeit für socklen_t existieren; Es wurde als Pflasterlösung erfunden, um die Unterschiede zwischen Systemen zu überbrücken, die das Traditionelle verwendeten int und solche, deren Betreuer das zu verwendende Argument eifrig geändert haben size_t. Während diese beiden Typen zu demselben ABI führten, gab es bis zu Systemen mit 64 Bit kein Problem size_tund 32-Bit int.

  • Kannst du verlinken, wo du das Zitat her hast? Es kann interessant sein, den Rest des Artikels zu lesen.

    – Shahbaz

    23. Juli 2013 um 8:42 Uhr


1283390cookie-checkWarum werden UNIX-Dateideskriptoren nicht durch ihren eigenen Typ implementiert, insbesondere in C++? [closed]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy