Sistemos skambučiai yra iškvietimai, kuriuos programa atlieka sistemos branduoliui, kad teiktų paslaugas, prie kurių programa neturi tiesioginės prieigos. Pavyzdžiui, suteikti prieigą prie įvesties ir išvesties įrenginių, tokių kaip monitoriai ir klaviatūros. Galime naudoti įvairias C programavimo kalboje pateiktas funkcijas įvesties/išvesties sistemos skambučiams, tokiems kaip kurti, atidaryti, skaityti, rašyti ir kt.
Prieš pereidami prie I/O sistemos skambučių, turime žinoti keletą svarbių terminų.
Svarbi terminija
Kas yra failo aprašas?
Failo aprašas yra sveikasis skaičius, unikaliai identifikuojantis atidarytą proceso failą.
Failo deskriptorių lentelė: failas deskriptorių lentelė yra sveikųjų skaičių masyvo indeksų rinkinys, kuris yra failų deskriptoriai, kurių elementai yra rodyklės į failų lentelės įrašus. Kiekvienam procesui operacinėje sistemoje pateikiama viena unikali failų deskriptorių lentelė.
Failų lentelės įrašas: Failų lentelės įrašai yra atviro failo pakaitalas atmintyje, kuri sukuriama apdorojant užklausą atidaryti failą ir šie įrašai palaiko failo padėtį.

Standartiniai failų aprašai : Kai kuris nors procesas prasideda, tada to proceso failų deskriptorių lentelės fd (failo deskriptorius) 0, 1, 2 atsidaro automatiškai, (pagal numatytuosius nustatymus) kiekvienas iš šių 3 fd nurodo failų lentelės įrašą, skirtą failui pavadinimu /dev/tty
/dev/tty : terminalo pakaitalas atmintyje.
Terminalas : kombinuotas klaviatūros/vaizdo ekranas.

Skaityti iš stdin => skaityti iš fd 0 : Kai rašome bet kurį simbolį iš klaviatūros, jis nuskaitomas nuo stdin iki fd 0 ir išsaugomas faile pavadinimu /dev/tty.
Rašykite į stdout => rašykite į fd 1 : Kai matome bet kokią išvestį į vaizdo ekraną, ji yra iš failo pavadinimu /dev/tty ir įrašoma į stdout ekrane per fd 1.
Rašykite į stderr => rašykite į fd 2 : Vaizdo įrašo ekrane matome bet kokią klaidą, ji taip pat iš to failo rašoma į stderr ekrane per fd 2.
Įvesties/išvesties sistemos skambučiai
Iš esmės iš viso yra 5 I/O sistemos iškvietimų tipai:
1. C sukurti
Funkcija create() naudojama kuriant naują tuščią failą C. Galime nurodyti failo, kurį norime sukurti, leidimą ir pavadinimą naudodami funkciją create(). Jis apibrėžiamas viduje antraštės failas ir vėliavėlės, kurios perduodamos kaip argumentai, yra apibrėžtos viduje antraštės failą.
Create() sintaksė C
int create (char * filename , mode_t mode );>
Parametras
- failo pavadinimas: failo, kurį norite sukurti, pavadinimą
- režimas: nurodo naujo failo teises.
Grąžinimo vertė
- grąžinti pirmąjį nepanaudotą failo deskriptorių (paprastai 3 pirmą kartą kuriant naudojimo procesą, nes 0, 1, 2 fd yra rezervuoti)
- grąžinti -1, kai klaida
Kaip C create() veikia OS
- Sukurkite naują tuščią failą diske.
- Sukurkite failų lentelės įrašą.
- Pirmąjį nenaudojamą failo aprašą nustatykite taip, kad jis nurodytų failų lentelės įrašą.
- Naudojamas grąžinimo failo deskriptorius, -1, jei nepavyko.
2. C atidarytas
Funkcija open() C yra naudojama norint atidaryti failą skaitymui, rašymui arba abiem. Jis taip pat gali sukurti failą, jei jo nėra. Jis apibrėžiamas viduje antraštės failas ir vėliavėlės, kurios perduodamos kaip argumentai, yra apibrėžtos viduje antraštės failą.
Open() sintaksė C
int open (const char* Path , int flags );>
Parametrai
- Kelias: Kelias į failą, kurį norime atidaryti.
- Naudoti absoliutus kelias pradedant nuo / kai esate ne dirba tame pačiame kataloge kaip C šaltinio failas.
- Naudokite santykinis kelias kuris yra tik failo pavadinimas su plėtiniu, kai esate dirba tame pačiame kataloge kaip C šaltinio failas.
- vėliavėlės: Jis naudojamas norint nurodyti, kaip norite atidaryti failą. Galime naudoti šias vėliavėles.
| Vėliavos | apibūdinimas |
|---|---|
| O_DONLY | Failas atidaromas tik skaitymo režimu. |
| O_WRONLY | Failas atidaromas tik rašymo režimu. |
| O_RDWR | Atidaro failą skaitymo ir rašymo režimu. |
| O_CREATE | Sukurkite failą, jei jo nėra. |
| O_EXCL | Neleiskite kurti, jei jis jau egzistuoja. |
| O_ PRIDĖTI | Atidaro failą ir perkelia žymeklį į turinio pabaigą. |
| O_ASYNC | Įjungti įvesties ir išvesties valdymą signalu. |
| O_CLOEXEC | Atidarytame faile įgalinkite uždarymo-exec režimą. |
| O_NONBLOCK | Išjungia atidaryto failo blokavimą. |
| O_TMPFILE | Nurodytu keliu sukurkite bevardį laikinąjį failą. |
Kaip C open() veikia OS
- Raskite diske esantį failą.
- Sukurkite failų lentelės įrašą.
- Pirmąjį nenaudojamą failo aprašą nustatykite taip, kad jis nurodytų failų lentelės įrašą.
- Naudojamas grąžinimo failo deskriptorius, -1, jei nepavyko.
C open() pavyzdys
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;> }> |
>
>
Išvestis
fd = 3>
3. C uždaryti
Funkcija close() programoje C praneša operacinei sistemai, kad baigėte su failo deskriptoriumi, ir uždaro failo deskriptoriaus nurodytą failą. Jis apibrėžiamas viduje antraštės failą.
Uždaryti () sintaksė C
int close(int fd);>
Parametras
- fd: F ile failo, kurį norite uždaryti, deskriptorius.
Grąžinimo vertė
- 0 apie sėkmę.
- -1 dėl klaidos.
Kaip C close() veikia OS
- Sunaikinti failų lentelės įrašą, nurodytą failo deskriptorių lentelės elementu fd
– Kol joks kitas procesas į tai nerodo! - Nustatyti failo deskriptorių lentelės elementą fd į NULL
1 pavyzdys: close() 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.
'>);> }> |
>
>
Išvestis
opened the fd = 3 closed the fd.>
2 pavyzdys:
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);> }> |
>
>
Išvestis
fd2 = 3>
Čia šiame kode grąžinamas pirmasis open(). 3 nes kai sukuriamas pagrindinis procesas, tada fd 0, 1, 2 jau paimti stdin , stdout, ir stderr . Taigi pirmasis nepanaudotas failo aprašas yra 3 failo deskriptorių lentelėje. Po to close() sistemos skambutis yra nemokamas 3 failų deskriptorius ir tada nustatykite 3 failų aprašai kaip nulinis . Taigi, kai iškvietėme antrąjį open(), tada pirmasis nepanaudotas fd taip pat yra 3 . Taigi, šios programos išvestis yra 3 .
4. C skaitymas
Iš failo, kurį nurodo failo aprašas fd, funkcija read() nuskaito nurodytą baitų kiekį cnt įvesties į atminties sritį, pažymėtą buf . Sėkmingas skaitymas () atnaujina failo prieigos laiką. Funkcija read () taip pat apibrėžta antraštės faile.
Skaitymo () sintaksė C
size_t read (int fd , void* buf , size_t cnt );>
Parametrai
- fd: failo, iš kurio turi būti nuskaitomi duomenys, deskriptorius.
- buf: buferis duomenims nuskaityti
- cnt: buferio ilgis
Grąžinimo vertė
- return Sėkmingai nuskaitytų baitų skaičius
- grąžinti 0 pasiekus failo pabaigą
- grąžinti -1 klaidos atveju
- grąžinimas -1 signalo pertraukimo atveju
Svarbūs punktai
- buf turi nurodyti tinkamą atminties vietą, kurios ilgis ne mažesnis nei nurodytas dydis dėl perpildymo.
- fd turėtų būti galiojantis failo deskriptorius, grąžintas iš open(), kad būtų atlikta skaitymo operacija, nes jei fd yra NULL, skaitymas turėtų sukelti klaidą.
- cnt yra prašomas perskaitytų baitų skaičius, o grąžinama vertė yra tikrasis nuskaitytų baitų skaičius. Be to, kartais perskaitytas sistemos iškvietimas turėtų nuskaityti mažiau baitų nei cnt.
Skaitymo () pavyzdys 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;> }> |
>
>
Išvestis
called read(3, c, 10). returned that 10 bytes were read. Those bytes are as follows: 0 0 0 foo.>
Tarkime, kad foobar.txt susideda iš 6 ASCII simbolių foobar. Kokia yra šios programos išvestis?
C
// 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);> }> |
>
>
Išvestis
c = f>
Deskriptoriai fd1 ir fd2 kiekvienas turi savo atvirą failų lentelės įrašą, todėl kiekvienas deskriptorius turi savo failo poziciją foobar.txt . Taigi, skaitykite iš fd2 skaito pirmąjį baitą foobar.txt , o išvestis yra c = f , ne c = o .
5. C rašyti
Rašo cnt baitus iš buf į failą arba lizdą, susietą su fd. cnt neturėtų būti didesnis nei INT_MAX (apibrėžtas limits.h antraštės faile). Jei cnt yra nulis, write () tiesiog grąžina 0, nemėgindamas jokio kito veiksmo.
Write () taip pat yra apibrėžtas viduje antraštės failą.
Write() sintaksė C
size_t write (int fd , void* buf , size_t cnt );>
Parametrai
- fd: failo aprašas
- buf: buferis duomenims rašyti.
- cnt: buferio ilgis.
Grąžinimo vertė
- grąžina baitų skaičių, parašytų apie sėkmę.
- grąžinti 0 pasiekus failo pabaigą.
- grąžinti -1 klaidos atveju.
- grąžinimas -1 signalo pertrūkiams.
Svarbūs punktai apie C rašymą
- Failas turi būti atidarytas rašymo operacijoms atlikti
- buf turi būti bent tokio ilgio, kiek nurodyta cnt, nes jei buf dydis yra mažesnis nei cnt, buf sukels perpildymo sąlygą.
- cnt yra prašomas įrašyti baitų skaičius, o grąžinama vertė yra tikrasis parašytų baitų skaičius. Tai atsitinka, kai fd turi mažiau rašomų baitų nei cnt.
- Jei rašymas () nutraukiamas signalo, efektas yra vienas iš šių:
- Jei write() dar neparašė jokių duomenų, jis grąžina -1 ir nustato errno į EINTR.
- Jei write () sėkmingai įrašė kai kuriuos duomenis, jis grąžina baitų skaičių, kurį parašė prieš nutraukdamas.
Write() pavyzdys C
C
k artimiausias kaimynas
// 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);> }> |
>
>
Išvestis
called write(3, 'hello geeks ', 12). it returned 11>
Čia, kai pamatysite faile foo.txt paleidę kodą, gausite a sveiki geikai . Jei faile foo.txt jau yra tam tikro turinio, tada rašymo sistemos iškvietimai perrašo turinį ir visas ankstesnis turinys yra ištrintas ir tik sveiki geikai turinys bus faile.
Pavyzdys: Spausdinkite hello world iš programos nenaudodami jokios printf funkcijos.
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;> }> |
>
>
Išvestis
hello world>
Šiame kode buf1 masyvo eilutė Labas pasauli pirmiausia įrašoma į stdin fd[0], tada ši eilutė įrašoma į stdin į buf2 masyvą. Po to įrašykite į buf2 masyvą į stdout ir spausdinkite išvestį Labas pasauli .