Wie kann überprüft werden, ob ein bestimmter Dateideskriptor, der in einer Variablen gespeichert ist, noch gültig ist?

Lesezeit: 5 Minuten

Ich habe einen Dateideskriptor in einer Variablen gespeichert, sagen wir var. Wie kann ich später überprüfen, ob dieser Deskriptor gültig ist?

  fdvar1= open(.....);
  fdvar2 = fdvar1;       // Please ignore the bad design

  ....
  // lots of loops , conditionals and threads. It can call close(fdvar2) also.  
  ....

  if(CheckValid(fdvar1)) // How can I do this check  ?
    write(fdvar1, ....);

Jetzt möchte ich prüfen, ob var1 (das noch den geöffneten Deskriptor enthält) noch gültig ist. Irgendwelche APIs dafür?

  • Warum wird das FD auf der C-Ebene statt auf der Betriebssystemebene kopiert?

    – Ignacio Vazquez-Abrams

    9. September 2012 um 16:18 Uhr

  • Siehe Handbuchseite für dup.

    – Irgendein Programmierer-Typ

    9. September 2012 um 16:19 Uhr

  • Selbst wenn Sie die Gültigkeit überprüfen können, ist das Ergebnis meist wertlos, da es möglich ist, dass eine andere geöffnete Datei denselben Deskriptor erhalten hat, nachdem das Original geschlossen wurde.

    – zwischenjay

    9. September 2012 um 16:20 Uhr

  • Dies wird in TLPI-Übung 5.4 ganz deutlich erwähnt.

    – Erich

    5. Mai 2015 um 5:52 Uhr

R.. GitHub STOP HELPING ICEs Benutzeravatar
R.. GitHub HÖREN SIE AUF, ICE ZU HELFEN

fcntl(fd, F_GETFD) ist der kanonisch billigste Weg, das zu überprüfen fd ist ein gültiger offener Dateideskriptor. Wenn Sie viele Chargen prüfen müssen, verwenden Sie poll mit einem Timeout von null und der events Mitglied auf 0 gesetzt und geprüft POLLNVAL in revents nach der Rückkehr ist effizienter.

Abgesehen davon ist die Operation “Prüfen, ob ein bestimmtes Ressourcen-Handle noch gültig ist” fast immer grundlegend falsch. Nachdem ein Ressourcen-Handle freigegeben wurde (z. B. ein fd is closed), kann sein Wert der nächsten solchen Ressource, die Sie zuweisen, neu zugewiesen werden. Wenn es verbleibende Referenzen gibt, die verwendet werden könnten, werden sie fälschlicherweise auf der neuen Ressource und nicht auf der alten operieren. Daher lautet die eigentliche Antwort wahrscheinlich: Wenn Sie anhand der Logik Ihres Programms noch nicht wissen, dass Sie grundlegende Logikfehler haben, die behoben werden müssen.

  • @R Angenommen, ich versuche, eine Bibliothek zu implementieren, die einen FD verarbeitet, beispielsweise die Pipe-Bibliothek, und ich bin derjenige, der die FD-Argumente an die Programme übergibt, die meine Bibliothek verwenden werden, ist es immer noch eine schlechte Praxis, auf FD-Validierung zu testen ? Oder ist es Pflicht?

    – Ravid Goldenberg

    18. Dezember 2014 um 8:00 Uhr

  • @petric: Ich verstehe deine Frage nicht. Als allgemeine Antwort sage ich ja, es ist schlecht (und bedeutungslos), “auf FD-Validierung zu testen”, aber wenn Sie bestimmte Bedenken haben, was Sie tun, sollten Sie wahrscheinlich eine neue Frage stellen, in der Sie danach fragen (und sich auf diese Frage/Antwort beziehen), anstatt in einem Kommentar zu fragen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    18. Dezember 2014 um 16:32 Uhr

  • Was ist, wenn ich Eltern- und Kindprozesse habe, die sich eine Pipe teilen? Im übergeordneten Prozess schließe ich das Leseende und schreibe das Ende der Pipe. Dann hat der Kindprozess immer noch ein gültiges Leseende. Wie funktioniert das?

    – Bean helfen

    28. Oktober 2018 um 10:52 Uhr

  • @HelpingBean: Ich verstehe nicht, wie das etwas mit dieser Frage zu tun hat. Wenn Sie dort eine echte Frage haben, posten Sie sie bitte als neue Frage (und senden Sie mir hier mit einem Link zur neuen Frage @).

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    28. Oktober 2018 um 17:58 Uhr


  • Das ist interessant. Aber für den Fall, dass ich eine Struktur teste, die einige Dateideskriptoren enthält. Und ich möchte eine Funktion testen, die die Dateideskriptoren schließt und den Speicher zurückfordert. Wäre es in einem solchen Fall richtig zu prüfen, ob die Dateideskriptoren geschlossen sind?

    – St.Antario

    6. April 2019 um 9:26 Uhr

Du kannst den … benutzen fcntl() Funktion:

int fd_is_valid(int fd)
{
    return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}

  • F_GETFD ist im Prinzip billiger, da es nur den (prozesslokalen) Dateideskriptor im Kernelspace dereferenziert, nicht die zugrunde liegende offene Dateibeschreibung (prozessgemeinsam), auf die es sich bezieht.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    9. September 2012 um 16:22 Uhr

  • Du solltest einstellen errno vor dem Anruf auf Null fcntl. errno könnte gleich sein EBADF bevor Sie Ihre Funktion aufrufen und fcntl wird es nur im Fehlerfall ändern.

    – Bilow

    29. November 2016 um 15:08 Uhr

  • @Bilow er prüft bereits auf einen Rückgabewert von -1was nur “im Fehlerfall” passiert, also Einstellung errno auf 0, bevor der Aufruf einfach überflüssig wäre.

    – Craig Barnes

    24. April 2019 um 10:04 Uhr

  • @CraigBarnes In der Tat

    – Bilow

    25. April 2019 um 10:45 Uhr

Benutzeravatar von wbao
wbao

Aus Dies Forumsartikel:

int is_valid_fd(int fd)
{
    return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
}

fcntl(GETFL) ist wahrscheinlich die billigste und am wenigsten wahrscheinlich fehlschlagende Operation, die Sie für einen Dateideskriptor ausführen können. Insbesondere legt die Spezifikation nahe, dass es nicht durch Signale unterbrochen werden kann und auch nicht durch irgendeine Art von Sperre beeinflusst wird, die irgendwo gehalten wird.

Benutzeravatar von David Grayson
David Grayson

Ich glaube nicht, dass es eine Funktion gibt, die Ihnen sagen kann, ob der Deskriptor noch gültig ist. Der Deskriptor ist normalerweise nur eine kleine Ganzzahl wie 6, und Ihre libc kann diese Zahl wiederverwenden, wenn Sie die Datei schließen und später eine neue öffnen.

Stattdessen sollten Sie die Verwendung in Betracht ziehen dup() um den Dateideskriptor zu kopieren. Indem Sie den Dateideskriptor duplizieren, anstatt denselben Deskriptor an mehreren Stellen zu verwenden, können Sie möglicherweise leichter feststellen, ob der Dateideskriptor noch gültig ist. Sie müssen nur daran denken, sowohl den ursprünglichen als auch den duplizierten Deskriptor zu schließen, wenn Sie fertig sind.

Benutzeravatar von John Hascall
John Hascal

Wenn Sie wissen möchten, ob es immer noch auf dieselbe Ressource verweist, scheint mir ein (nicht perfekter) Ansatz zu sein fstat() den Deskriptor einfach nach dem Öffnen und später können Sie es erneut tun und die Ergebnisse vergleichen. Beginnen Sie mit dem Betrachten .st_mode& S_IFMT und gehen Sie von dort aus – ist es ein Dateisystemobjekt? Ansehen .st_dev / .st_ino. Ist es eine Steckdose? Versuchen getsockname(), getpeername(). Es wird nicht 100% sicher sein, aber es kann Ihnen sagen, ob es definitiv nicht dasselbe ist.

Benutzeravatar von flozn
flozn

Ich habe dieses Problem für mich gelöst. Ich weiß nicht, ob es für allgemeine Zwecke verwendet werden kann, aber für serielle Verbindungen funktioniert es gut (zB /dev/ttyUSB0)!

struct stat s;
fstat(m_fileDescriptor, &s);

// struct stat::nlink_t   st_nlink;   ... number of hard links 
if( s.st_nlink < 1 ){
 // treat device disconnected case
}

Für Details siehe zB Manpage http://linux.die.net/man/2/fstat

Gruß Flo

1413400cookie-checkWie kann überprüft werden, ob ein bestimmter Dateideskriptor, der in einer Variablen gespeichert ist, noch gültig ist?

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

Privacy policy