close(2)

NUME
close - închide un descriptor de fișier

BIBLIOTECA
Biblioteca C standard (libc, -lc)

SINOPSIS
#include <unistd.h>

int close(int fd);

DESCRIERE
close() închide un descriptor de fișier, astfel încât acesta să nu se mai refere la niciun fișier și să poată fi reutilizat. Orice blocare de înregistrare (a se vedea fcntl(2)) deținută pe fișierul cu care a fost asociată și deținută de proces este eliminată, indiferent de descriptorul de fișier care a fost utilizat pentru obținerea blocării. Acest lucru are unele consecințe nefericite și trebuie să fiți foarte atenți atunci când utilizați blocarea înregistrării consultative. A se vedea fcntl(2) pentru discutarea riscurilor și consecințelor, precum și pentru blocajele de descriere a fișierului deschis (probabil preferate).

Dacă fd este ultimul descriptor de fișier care se referă la descrierea fișierului deschis subiacent (a se vedea open(2)), resursele asociate descrierii fișierului deschis sunt eliberate; dacă descriptorul de fișier a fost ultima referință la un fișier care a fost eliminat utilizând unlink(2), fișierul este șters.

VALOAREA RETURNATĂ
close() returnează zero în caz de succes. În caz de eroare, este returnat -1, iar errno este configurată pentru a indica eroarea.

ERORI-IEȘIRE

EBADF
    fd nu este un descriptor de fișier deschis valid.

EINTR
    Apelul close() a fost întrerupt de un semnal; consultați signal(7).

EIO A apărut o eroare de In/Ieș.

ENOSPC
EDQUOT
    Pe NFS, aceste erori nu sunt în mod normal raportate la prima scriere care depășește spațiul de stocare disponibil, ci la o scriere ulterioară write(2), fsync(2) sau close().

Consultați secțiunea AVERTISMENTE pentru o discuție a motivului pentru care close() nu ar trebui să fie reapelat după o eroare.

STANDARDE
POSIX.1-2008.

ISTORIC
4.3BSD, SVr4, POSIX.1-1988.

NOTE
Fanionul de descriptor de fișier close-on-exec poate fi utilizat pentru a se asigura că un descriptor de fișier este închis automat în urma unui execve(2) reușit; consultați fcntl(2) pentru detalii.

AVERTISMENTE
O închidere reușită nu garantează că datele au fost salvate cu succes pe disc, deoarece nucleul utilizează memoria cache pentru a amâna scrierile. De obicei, sistemele de fișiere nu curăță tampoanele atunci când un fișier este închis. Dacă trebuie să fiți siguri că datele sunt stocate fizic pe discul de bază, utilizați fsync(2); (aceasta va depinde de hardware-ul discului în acest moment).

  Procesele cu mai multe fire de execuție și close()
Probabil că nu este înțelept să închideți descriptorii de fișier în timp ce aceștia pot fi utilizați de apeluri de sistem în alte fire de execuție din același proces. Deoarece un descriptor de fișier poate fi reutilizat, există unele condiții de concurență ascunse care pot provoca efecte secundare neintenționate.

În plus, luați în considerare următorul scenariu în care două fire efectuează operații pe același descriptor de fișier:

(1) Un fir este blocat într-un apel de sistem I/O pe descriptorul de fișier. De exemplu, încearcă să efectueze write(2) pe o conductă care este deja plină sau încearcă să efectueze read(2) de la un soclu de flux care nu are în prezent date disponibile.

(2) Un alt fir închide descriptorul de fișier.

Comportamentul în această situație variază de la un sistem la altul. Pe unele sisteme, atunci când descriptorul de fișier este închis, apelul de sistem blocant returnează imediat cu o eroare.

Pe Linux (și posibil pe alte sisteme), comportamentul este diferit: apelul de sistem I/O blocant deține o referință la descrierea fișierului deschis, iar această referință menține descrierea deschisă până la finalizarea apelului de sistem I/O. (Consultați open(2) pentru o discuție despre descrierile de fișiere deschise). Astfel, apelul de sistem blocant din primul fir poate fi finalizat cu succes după efectuarea close() din al doilea fir.

  Gestionarea răspunsurilor eronate de la close()
Un programator atent va verifica valoarea de returnare a close(), deoarece este foarte posibil ca erorile de la o operație anterioară write(2) să fie raportate numai la close() final care eliberează descrierea fișierului deschis. Ne verificarea valorii de returnare la închiderea unui fișier poate duce la pierderea silențioasă de date. Acest lucru poate fi observat în special cu NFS și cu cota de disc.

Rețineți, totuși, că o returnare în caz de eșec ar trebui utilizată numai în scopuri de diagnosticare (de exemplu, un avertisment adresat aplicației că este posibil să mai existe operații I/O în așteptare sau că este posibil să fi existat operații I/O eșuate) sau în scopuri de remediere (de exemplu, scrierea fișierului încă o dată sau crearea unei copii de rezervă).

Reîncercarea operației close() după un eșec este un lucru greșit de făcut, deoarece acest lucru poate cauza închiderea unui descriptor de fișier reutilizat de la un alt fir de execuție. Acest lucru se poate întâmpla deoarece nucleul Linux eliberează întotdeauna descriptorul de fișier la începutul operației de închidere, eliberându-l pentru reutilizare; pașii care pot returna o eroare, cum ar fi trimiterea datelor către sistemul de fișiere sau dispozitiv, au loc doar mai târziu în operația de închidere.

În mod similar, multe alte implementări închid întotdeauna descriptorul de fișier (cu excepția cazului EBADF, ceea ce înseamnă că descriptorul de fișier a fost nevalid) chiar dacă ulterior raportează o eroare la returnarea de la operația close(). POSIX.1-2008 nu a menționat nimic în legătură cu acest aspect.

Un programator atent care dorește să știe despre erorile I/O poate precede close() cu un apel la fsync(2).

Eroarea EINTR este un caz oarecum special. În ceea ce privește eroarea EINTR, POSIX.1-2008 spune:

    Dacă close() este întrerupt de un semnal care trebuie captat, acesta returnează -1 cu errno configurată la EINTR și starea lui fd este nespecificată.

Acest lucru permite comportamentul care apare pe Linux și în multe alte implementări, unde, ca și în cazul altor erori care pot fi raportate de close(), descriptorul de fișier este garantat a fi închis. Cu toate acestea, aceasta permite și o altă posibilitate: ca implementarea să returneze o eroare EINTR și să mențină descriptorul de fișier deschis. Conform documentației sale, close() de la HP-UX face acest lucru. Apelantul trebuie apoi să utilizeze încă o dată close() pentru a închide descriptorul de fișier, pentru a evita scurgerile de informații din descriptorul de fișier. Această divergență în comportamentele de implementare reprezintă un obstacol dificil pentru aplicațiile portabile, deoarece în multe implementări, close() nu trebuie să fie apelat din nou după o eroare EINTR, iar în cel puțin una, close() trebuie să fie apelat din nou.

POSIX.1-2024 a standardizat comportamentul HP-UX, făcând Linux și multe alte implementări neconforme. Nu există planuri de modificare a comportamentului în Linux.

CONSULTAȚI ȘI
close_range(2), fcntl(2), fsync(2), open(2), shutdown(2), unlink(2), fclose(3)

TRADUCERE
Traducerea în limba română a acestui manual a fost făcută de Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>

Această traducere este documentație gratuită; citiți Licența publică generală GNU Versiunea 3 (https://www.gnu.org/licenses/gpl-3.0.html) sau o versiune ulterioară cu privire la condiții privind drepturile de autor. NU se asumă NICIO RESPONSABILITATE.

Dacă găsiți erori în traducerea acestui manual, vă rugăm să trimiteți un e-mail la translation-team-ro@lists.sourceforge.net.