Ich habe einen fd-Deskriptor, aus dem ich durch Aufrufen lesen kann read(fd, buffer,...)
. Jetzt möchte ich prüfen, ob es etwas zu lesen gibt, bevor ich den Anruf tatsächlich tätige, da der Anruf blockiert ist. Wie mache ich das?
Nicht blockierender Aufruf zum Lesen des Deskriptors
Kleines Schach
Richter Maygarden
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
Das obige Code-Snippet konfiguriert einen solchen Deskriptor für den nicht blockierenden Zugriff. Wenn beim Aufrufen von read keine Daten verfügbar sind, schlägt der Systemaufruf mit einem Rückgabewert von -1 fehl und errno wird auf EAGAIN gesetzt. Siehe die Funktion man-Seiten für weitere Informationen.
Alternativ können Sie verwenden auswählen mit einem konfigurierbaren Timeout zum Überprüfen und/oder Warten eines bestimmten Zeitintervalls auf weitere Daten. Diese Methode ist wahrscheinlich das, was Sie wollen und kann viel effizienter sein.
-
Und dann prüfen Sie, ob -1 von zurückgegeben wird
read
und daserrno
istEAGAIN
.– mu ist zu kurz
11. April 2011 um 2:06 Uhr
-
gutes Dokument über Datei mit nicht blockierender Support-Einstellung errno at offene Gruppe
– qrtLs
4. Juli 2016 um 16:11 Uhr
-
Dies ist NICHT die richtige Antwort. O_NONBLOCK gegen ein reguläres fs hat keine Wirkung (read() blockiert weiter) und select() meldet das fd immer fälschlicherweise als “bereit”. Zuverlässiges, nicht blockierendes IO für reguläre Dateien unter Linux wird grundsätzlich (und leider) nicht unterstützt.
– Giampaolo Rodola
19. Dezember 2016 um 12:14 Uhr
-
Etwas gut Quellen auf reguläre Dateien und nicht blockierende E/A. jedoch, wenn
fd
ist stdin, dann scheint es harmlos zu seinO_NONBLOCK
Beschleunigen Sie die Dinge beim Lesen von einem Terminal / einer Pipe und tun Sie nichts, wenn Sie von einer Datei lesen.– Paul A. Jungwirth
6. Mai 2017 um 7:07 Uhr
R.. GitHub HÖREN SIE AUF, ICE ZU HELFEN
Verwenden select
oder poll
um abzufragen, ob der Dateideskriptor Daten zum Lesen bereithält:
fd_set fds;
FD_ZERO(&fds);
FD_SET(&fds, fd);
if (select(fd+1, &fds, 0, 0)==1) /* there is data available */
-
Ist nicht
FD_SET(fd, &fds);
stattdessen ?– malat
27. Januar 2015 um 12:46 Uhr
-
Wahrscheinlich, aber
select
ist sowieso eine schreckliche Idee, weilFD_SET
ruft UB auf, wennfd>=FD_SETSIZE
. Benutz einfachpoll
.– R.. GitHub HÖR AUF, EIS ZU HELFEN
27. Januar 2015 um 17:16 Uhr
-
poll()
ist jetzt in POSIX standardisiert, sodass es immer anstelle von verwendet werden kannselect()
. pubs.opengroup.org/onlinepubs/009695399/functions/poll.html– Lassi
3. Mai 2018 um 8:09 Uhr
-
Ja,
poll
sollte stattdessen verwendet werden.– R.. GitHub HÖR AUF, EIS ZU HELFEN
3. Mai 2018 um 16:17 Uhr
-
IIRC-Abfrage auf macOS UND serieller Schnittstelle funktioniert nicht. Ich konnte die Referenz jetzt nicht finden, aber ich habe eine deutliche Erinnerung, dass dies der Fall ist oder war. Da dies eine alte Frage war, die nicht Linux-spezifisch war, denke ich, dass die Empfehlung, poll() zu verwenden, schlecht sein könnte.
– nyholku
17. März 2020 um 6:16 Uhr
Je nachdem, was Sie tun, können Sie das Problem möglicherweise umkrempeln und verwenden select
um Ihnen mitzuteilen, wenn Ihr Dateideskriptor etwas zu lesen hat.
Ankur Soni
Abfrage für Timeout verwenden:
struct pollfd p;
int n;
while ((n = poll(&p, 1, iTo)) < 0)
{
if (errno == EAGAIN || errno == EINTR)
continue;
}
if (!n) {
errno = ETIMEDOUT;
}
while ((len = read(Fd, anyBuff, sizeof(anyenter code hereBuff))) < 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
}
Ich denke, Sie sollten verwenden select
oder poll
Funktionen, um zu prüfen, ob es etwas aus dem Deskriptor zu lesen gibt.
-
Können Sie weitere Details hinzufügen? Ein Beispiel wäre schön.
– Nathan F.
8. Oktober 2019 um 22:56 Uhr
Novin Shahroudi
Überprüfen Sie die API oder das System/Tool, das Sie für Ihren spezifischen Programmierzweck verwenden. (Deskriptoren/Dateideskriptoren haben viele Anwendungen in der Linux-Programmierung, wie z. B. Socket-Programmierung, Dateimanipulation, Shared_Memory usw.)
Zum Beispiel habe ich einmal inotify verwendet (zur Überwachung von Dateisystemereignissen). Diese API gibt Ihnen die Möglichkeit, vom ersten Punkt an eine nicht blockierende Datei zu erstellen, und es besteht keine Notwendigkeit, fcntl oder ähnliche APIs zu verwenden, um den erstellten Dateideskriptor zu ändern.
Wahrscheinlich haben andere Tools oder APIs, die Sie verwenden werden, eine solche Funktionalität, und Sie können eine solche Option bei ihrer Initiierung oder solchen Schritten festlegen (überprüfen Sie dies zuerst).
Aber im Allgemeinen ist ja die Verwendung von fcntl die Antwort, und es könnte interessant sein zu wissen, dass inotify selbst auch fcntl selbst verwendet. (siehe Handbuchseiten von Linux)
select() kann Ihnen die gleiche Funktionalität bieten wie es auf Dateideskriptoren zum Überwachen von Ereignissen mit einer bestimmten begrenzten Zeit arbeitet, aber denken Sie daran, dass die Hauptverwendung von select die Überwachung ist mehrere Dateideskriptoren.
-
Können Sie weitere Details hinzufügen? Ein Beispiel wäre schön.
– Nathan F.
8. Oktober 2019 um 22:56 Uhr
Das Verhalten von read in Bezug auf das Blockieren variiert je nach Deskriptortyp. Zu welcher Art von Gerät passt
fd
verweisen?– kqnr
11. April 2011 um 1:59 Uhr
Standardeingänge blockieren gerade jetzt
– Kleines Schach
11. April 2011 um 2:00 Uhr
@KenRockot also, wenn ich eine normale Datei habe, ist es anders als zum Beispiel fd, das ein socketDescriptor ist?
– Bionix1441
19. April 2016 um 17:18 Uhr