Apelurile de sistem sunt apelurile pe care un program le face către nucleul sistemului pentru a furniza serviciile la care programul nu are acces direct. De exemplu, oferind acces la dispozitivele de intrare și ieșire, cum ar fi monitoare și tastaturi. Putem folosi diverse funcții furnizate în limbajul de programare C pentru apeluri de sistem de intrare/ieșire, cum ar fi crearea, deschiderea, citirea, scrierea etc.
Înainte de a trece la Apelurile de sistem I/O, trebuie să știm despre câțiva termeni importanți.
Terminologie importantă
Ce este descriptorul de fișier?
Descriptorul de fișier este un număr întreg care identifică în mod unic un fișier deschis al procesului.
Tabel Descriptor de fișier: Un fișier tabelul de descriptori este o colecție de indici de matrice întregi care sunt descriptori de fișiere în care elementele sunt pointeri către intrările tabelului de fișiere. Un tabel unic de descriptori de fișiere este furnizat în sistemul de operare pentru fiecare proces.
Intrare în tabelul fișierului: Intrările din tabelul de fișiere sunt o structură surogat în memorie pentru un fișier deschis, care este creată la procesarea unei cereri de deschidere a fișierului și aceste intrări mențin poziția fișierului.
Descriptori de fișiere standard : Când începe orice proces, atunci tabelul de descriptori a fișierului de proces fd(descriptor de fișier) 0, 1, 2 se deschide automat, (în mod implicit) fiecare dintre aceste 3 fd face referire la intrarea tabelului de fișiere pentru un fișier numit /dev/tty
/dev/tty : surogat în memorie pentru terminal.
Terminal : Combinație tastatură/ecran video.
Citiți din stdin => citiți din fd 0 : Ori de câte ori scriem orice caracter de la tastatură, acesta citește de la stdin până la fd 0 și salvează într-un fișier numit /dev/tty.
Scrieți în stdout => scrieți în fd 1 : Ori de câte ori vedem orice ieșire pe ecranul video, aceasta este din fișierul numit /dev/tty și scrisă în stdout în ecran prin fd 1.
Scrieți în stderr => scrieți în fd 2 : Vedem orice eroare pe ecranul video, este și din acel fișier scrieți în stderr în ecran prin fd 2.
Apeluri de sistem de intrare/ieșire
Practic, există în total 5 tipuri de apeluri de sistem I/O:
1. C creați
Funcția create() este folosită pentru a crea un nou fișier gol în C. Putem specifica permisiunea și numele fișierului pe care dorim să-l creăm folosind funcția create(). Este definit în interior fișierul antet și steagurile care sunt transmise ca argumente sunt definite în interior fișier antet.
Sintaxa create() în C
int create (char * filename , mode_t mode );>
Parametru
- nume de fișier: numele fișierului pe care doriți să-l creați
- modul: indică permisiunile noului fișier.
Valoare returnată
- returnează primul descriptor de fișier neutilizat (în general 3 la prima creare a utilizării în proces, deoarece 0, 1, 2 fd sunt rezervate)
- returnează -1 când o eroare
Cum funcționează C create() în sistemul de operare
- Creați un nou fișier gol pe disc.
- Creați o intrare în tabelul de fișiere.
- Setați primul descriptor de fișier neutilizat pentru a indica intrarea în tabelul de fișiere.
- Returnează descriptorul de fișier folosit, -1 la eșec.
2. C deschis
Funcția open() din C este folosită pentru a deschide fișierul pentru citire, scriere sau ambele. De asemenea, este capabil să creeze fișierul dacă acesta nu există. Este definit în interior fișierul antet și steagurile care sunt transmise ca argumente sunt definite în interior fișier antet.
Sintaxa lui open() în C
int open (const char* Path , int flags );>
Parametrii
- Cale: Calea către fișierul pe care vrem să-l deschidem.
- Folosește cale absolută începând cu / când ești nu lucrând în același director ca fișier sursă C.
- Utilizare cale relativă care este doar numele fișierului cu extensie, atunci când sunteți lucrând în același director ca fișier sursă C.
- steaguri: Este folosit pentru a specifica modul în care doriți să deschideți fișierul. Putem folosi următoarele steaguri.
Steaguri | Descriere |
---|---|
O_RDONLY | Deschide fișierul în modul numai citire. |
O_NEGRESIT | Deschide fișierul în modul numai de scriere. |
O_RDWR | Deschide fișierul în modul citire și scriere. |
O_CREAT | Creați un fișier dacă nu există. |
O_EXCL | Preveniți crearea dacă există deja. |
O_ ANEXA | Deschide fișierul și plasează cursorul la sfârșitul conținutului. |
O_ASYNC | Activați controlul intrării și ieșirii prin semnal. |
O_CLOEXEC | Activați modul close-on-exec pe fișierul deschis. |
O_NONBLOCK | Dezactivează blocarea fișierului deschis. |
O_TMPFILE | Creați un fișier temporar fără nume pe calea specificată. |
Cum funcționează C open() în sistemul de operare
- Găsiți fișierul existent pe disc.
- Creați o intrare în tabelul de fișiere.
- Setați primul descriptor de fișier neutilizat pentru a indica intrarea în tabelul de fișiere.
- Returnează descriptorul de fișier folosit, -1 la eșec.
Exemplu de C open()
C
// C program to illustrate> // open system call> #include> #include> #include> #include> extern> int> errno> ;> int> main()> {> > // if file does not have in directory> > // then file foo.txt is created.> > int> fd = open(> 'foo.txt'> , O_RDONLY | O_CREAT);> > printf> (> 'fd = %d
'> , fd);> > if> (fd == -1) {> > // print which type of error have in a code> > printf> (> 'Error Number % d
'> ,> errno> );> > // print program detail 'Success or failure'> > perror> (> 'Program'> );> > }> > return> 0;> }> |
>
>
Ieșire
fd = 3>
3. C aproape
Funcția close() din C spune sistemului de operare că ați terminat cu un descriptor de fișier și închide fișierul indicat de descriptorul de fișier. Este definit în interior fișier antet.
teoria arborilor și grafurilor
Sintaxa close() în C
int close(int fd);>
Parametru
- fd: F descriptor de fișier al fișierului pe care doriți să-l închideți.
Valoare returnată
- 0 asupra succesului.
- -1 pe eroare.
Cum funcționează C close() în sistemul de operare
- Distrugeți intrarea din tabelul de fișiere la care se face referire de elementul fd din tabelul descriptor de fișiere
– Atâta timp cât niciun alt proces nu indică acest lucru! - Setați elementul fd din tabelul descriptor al fișierului la NUL
Exemplul 1: close() în C
C
// C program to illustrate close system Call> #include> #include> #include> int> main()> {> > int> fd1 = open(> 'foo.txt'> , O_RDONLY);> > if> (fd1 <0) {> > perror> (> 'c1'> );> > exit> (1);> > }> > printf> (> 'opened the fd = % d
'> , fd1);> > // Using close system Call> > if> (close(fd1) <0) {> > perror> (> 'c1'> );> > exit> (1);> > }> > printf> (> 'closed the fd.
'> );> }> |
>
>
Ieșire
opened the fd = 3 closed the fd.>
Exemplul 2:
C
// C program to illustrate close system Call> #include> #include> int> main()> {> > // assume that foo.txt is already created> > int> fd1 = open(> 'foo.txt'> , O_RDONLY, 0);> > close(fd1);> > > // assume that baz.tzt is already created> > int> fd2 = open(> 'baz.txt'> , O_RDONLY, 0);> > > printf> (> 'fd2 = % d
'> , fd2);> > exit> (0);> }> |
>
>
Ieșire
fd2 = 3>
Aici, în acest cod se întoarce mai întâi open() 3 deoarece atunci când procesul principal este creat, atunci fd 0, 1, 2 sunt deja luate de stdin , stdout, și stderr . Deci primul descriptor de fișier neutilizat este 3 în tabelul descriptor al fișierului. După aceea, apelul de sistem close() este liber 3 descriptori de fișiere și apoi setați 3 descriptori de fișiere ca nul . Deci, când am apelat al doilea open(), atunci primul fd neutilizat este și el 3 . Deci, rezultatul acestui program este 3 .
4. C citit
Din fișierul indicat de descriptorul de fișier fd, funcția read() citește cantitatea specificată de octeți cnt de intrare în zona de memorie indicată de buf . Un read() cu succes actualizează timpul de acces pentru fișier. Funcția read() este definită și în interiorul fișierului antet.
Sintaxa read() în C
size_t read (int fd , void* buf , size_t cnt );>
Parametrii
- fd: descriptor de fișier al fișierului din care urmează să fie citite datele.
- buf: tampon din care să citească datele
- cnt: lungimea tamponului
Valoare returnată
- return Numărul de octeți citiți la succes
- returnați 0 când ajungeți la sfârșitul fișierului
- returnează -1 la eroare
- returnează -1 la întreruperea semnalului
Puncte importante
- buf trebuie să indice o locație de memorie validă cu o lungime nu mai mică decât dimensiunea specificată din cauza depășirii.
- fd ar trebui să fie un descriptor de fișier valid returnat de la open() pentru a efectua operația de citire, deoarece dacă fd este NULL, citirea ar trebui să genereze o eroare.
- cnt este numărul solicitat de octeți citiți, în timp ce valoarea returnată este numărul real de octeți citiți. De asemenea, uneori, citirea apelului de sistem ar trebui să citească mai puțini octeți decât cnt.
Exemplu de read() în C
C
// C program to illustrate> // read system Call> #include> #include> #include> int> main()> {> > int> fd, sz;> > char> * c = (> char> *)> calloc> (100,> sizeof> (> char> ));> > fd = open(> 'foo.txt'> , O_RDONLY);> > if> (fd <0) {> > perror> (> 'r1'> );> > exit> (1);> > }> > sz = read(fd, c, 10);> > printf> (> 'called read(% d, c, 10). returned that'> > ' %d bytes were read.
'> ,> > fd, sz);> > c[sz] => ' '> ;> > printf> (> 'Those bytes are as follows: % s
'> , c);> > return> 0;> }> |
>
>
Ieșire
called read(3, c, 10). returned that 10 bytes were read. Those bytes are as follows: 0 0 0 foo.>
Să presupunem că foobar.txt este format din cele 6 caractere ASCII foobar. Atunci care este rezultatul următorului program?
C
cadru de primăvară
// C program to illustrate> // read system Call> #include> #include> #include> #include> int> main()> {> > char> c;> > int> fd1 = open(> 'sample.txt'> , O_RDONLY, 0);> > int> fd2 = open(> 'sample.txt'> , O_RDONLY, 0);> > read(fd1, &c, 1);> > read(fd2, &c, 1);> > printf> (> 'c = %c
'> , c);> > exit> (0);> }> |
>
>
java convertește char în int
Ieșire
c = f>
Descriptorii fd1 și fd2 fiecare are propria sa intrare în tabelul de fișiere deschise, astfel încât fiecare descriptor are propria poziție a fișierului pentru foobar.txt . Astfel, cititul din fd2 citește primul octet al foobar.txt , iar rezultatul este c = f , nu c = o .
5. C scrie
Scrie cnt octeți din buf în fișierul sau socketul asociat cu fd. cnt nu trebuie să fie mai mare decât INT_MAX (definit în fișierul antet limits.h). Dacă cnt este zero, write() returnează pur și simplu 0 fără a încerca nicio altă acțiune.
Scrie () este, de asemenea, definit în interior fișier antet.
Sintaxa scrierii () în C
size_t write (int fd , void* buf , size_t cnt );>
Parametrii
- fd: descriptor de fișier
- buf: tampon din care să scrieți datele.
- cnt: lungimea tamponului.
Valoare returnată
- returnează numărul de octeți scriși la succes.
- returnați 0 când ajungeți la sfârșitul fișierului.
- returnează -1 la eroare.
- returnează -1 la întreruperile semnalului.
Puncte importante despre C scrie
- Fișierul trebuie deschis pentru operațiuni de scriere
- buf trebuie să fie cel puțin atât de lungă cât este specificat de cnt, deoarece dacă dimensiunea buf este mai mică decât cnt, atunci buf va duce la starea de depășire.
- cnt este numărul solicitat de octeți de scris, în timp ce valoarea returnată este numărul real de octeți scriși. Acest lucru se întâmplă când fd are un număr mai mic de octeți de scris decât cnt.
- Dacă write() este întrerupt de un semnal, efectul este unul dintre următoarele:
- Dacă write() nu a scris încă nicio dată, returnează -1 și setează errno la EINTR.
- Dacă write() a scris cu succes unele date, returnează numărul de octeți pe care i-a scris înainte de a fi întrerupt.
Exemplu de write() în C
C
// C program to illustrate> // write system Call> #include> #include> main()> {> int> sz;> int> fd = open(> 'foo.txt'> , O_WRONLY | O_CREAT | O_TRUNC, 0644);> if> (fd <0)> {> > perror> (> 'r1'> );> > exit> (1);> }> sz = write(fd,> 'hello geeks
'> ,> strlen> (> 'hello geeks
'> ));> printf> (> 'called write(% d, 'hello geeks
', %d).'> > ' It returned %d
'> , fd,> strlen> (> 'hello geeks
'> ), sz);> close(fd);> }> |
>
>
Ieșire
called write(3, 'hello geeks ', 12). it returned 11>
Aici, când vedeți în fișierul foo.txt după rularea codului, obțineți un salut tocilari . Dacă fișierul foo.txt are deja conținut în el, atunci scrierea unui apel de sistem suprascrie conținutul și tot conținutul anterior este șters si doar salut tocilari continutul va avea in fisier.
Exemplu: Imprimați hello world din program fără a utiliza nicio funcție printf.
C
// C program to illustrate> // I/O system Calls> #include> #include> #include> #include> int> main(> void> )> {> > int> fd[2];> > char> buf1[12] => 'hello world'> ;> > char> buf2[12];> > // assume foobar.txt is already created> > fd[0] = open(> 'foobar.txt'> , O_RDWR);> > fd[1] = open(> 'foobar.txt'> , O_RDWR);> > write(fd[0], buf1,> strlen> (buf1));> > write(1, buf2, read(fd[1], buf2, 12));> > close(fd[0]);> > close(fd[1]);> > return> 0;> }> |
>
>
Ieșire
hello world>
În acest cod, șirul matricei buf1 Salut Lume este mai întâi scris în stdin fd[0] apoi după aceea acest șir scrie în stdin în matricea buf2. După aceea, scrieți în matricea buf2 în stdout și imprimați ieșirea Salut Lume .