logo

Input-output järjestelmäkutsut C | Luo, avaa, sulje, lue, kirjoita

Järjestelmäkutsut ovat kutsuja, joita ohjelma tekee järjestelmäytimelle tarjotakseen palveluita, joihin ohjelmalla ei ole suoraa pääsyä. Esimerkiksi pääsyn tarjoaminen syöttö- ja tulostuslaitteisiin, kuten näyttöihin ja näppäimistöihin. Voimme käyttää erilaisia ​​C-ohjelmointikielen toimintoja syöttö-/tulostusjärjestelmäkutsuihin, kuten luomiseen, avaamiseen, lukemiseen, kirjoittamiseen jne.

Ennen kuin siirrymme I/O-järjestelmäkutsuihin, meidän on tiedettävä muutama tärkeä termi.



Tärkeää terminologiaa

Mikä on tiedostokuvaaja?

Tiedostokuvaaja on kokonaisluku, joka yksilöi prosessin avoimen tiedoston.

Tiedoston kuvaustaulukko: Tiedosto deskriptoritaulukko on kokoelma kokonaislukutaulukon indeksejä, jotka ovat tiedostokuvaajia, joiden elementit ovat osoittimia tiedostotaulukon merkintöihin. Käyttöjärjestelmässä on yksi yksilöllinen tiedostokuvaustaulukko jokaista prosessia varten.



Tiedostotaulukon merkintä: Tiedostotaulukkomerkinnät ovat rakennemuistissa oleva avoimen tiedoston korvike, joka luodaan käsiteltäessä tiedoston avaamispyyntöä ja nämä merkinnät säilyttävät tiedoston sijainnin.

Tiedostotaulukkomerkintä C-muodossa

Vakiotiedostokuvaukset : Kun mikä tahansa prosessi käynnistyy, kyseisen prosessin tiedostokuvaustaulukon fd(tiedostokuvaaja) 0, 1, 2 avautuu automaattisesti, (oletusarvoisesti) jokainen näistä 3 fd viittaa tiedostotaulukkomerkintään tiedostolle nimeltä /dev/tty



/dev/tty : Päätteen muistissa oleva korvike.

Terminaali : Näppäimistön/videon yhdistelmä.

Vakiotiedostokuvaukset

Lue stdinistä => lue fd 0:sta : Aina kun kirjoitamme mitä tahansa merkkiä näppäimistöltä, se lukee stdin:stä fd 0:aan ja tallentaa tiedostoon nimeltä /dev/tty.
Kirjoita stdoutiin => kirjoita fd 1:een : Aina kun näemme ulostulon videonäytölle, se tulee tiedostosta nimeltä /dev/tty ja kirjoitetaan stdoutiin näytössä fd 1:n kautta.
Kirjoita stderriin => kirjoita fd 2:een : Näemme virheitä videonäytössä, se on myös tuosta tiedostosta, joka kirjoitetaan stderriin näytössä fd 2:n kautta.

Input/Output System Calls

Periaatteessa on yhteensä 5 tyyppiä I/O-järjestelmäkutsuja:

1. C luo

Create()-funktiolla luodaan uusi tyhjä tiedosto C-kielessä. Voimme määrittää luotavan tiedoston luvan ja nimen käyttämällä create()-funktiota. Se on määritelty sisällä otsikkotiedosto ja argumentteina välitettävät liput määritellään sisällä otsikkotiedosto.

Create()-funktion syntaksi C:ssä

int   create  (char *  filename  , mode_t   mode  );>

Parametri

  • Tiedoston nimi: sen tiedoston nimi, jonka haluat luoda
  • tila: ilmaisee uuden tiedoston käyttöoikeudet.

Palautusarvo

  • palauta ensimmäinen käyttämätön tiedostokuvaus (yleensä 3, kun luot ensimmäisen käytön prosessissa, koska 0, 1, 2 fd on varattu)
  • palauttaa -1 virheen sattuessa

Kuinka C create() toimii käyttöjärjestelmässä

  • Luo uusi tyhjä tiedosto levylle.
  • Luo tiedostotaulukkomerkintä.
  • Aseta ensimmäinen käyttämätön tiedostokuvaaja osoittamaan tiedostotaulukon merkintää.
  • Palauta tiedostokuvaaja käytetty, -1 epäonnistuessa.

2. C auki

C:n open()-funktiota käytetään tiedoston avaamiseen lukemista, kirjoittamista tai molempia varten. Se pystyy myös luomaan tiedoston, jos sitä ei ole olemassa. Se on määritelty sisällä otsikkotiedosto ja argumentteina välitettävät liput määritellään sisällä otsikkotiedosto.

Open()-funktion syntaksi C:ssä

int   open   (const char*   Path  , int   flags  );>

Parametrit

  • Polku: Polku tiedostoon, jonka haluamme avata.
    • Käytä absoluuttinen polku alkaen / kun olet ei työskentelevät samassa hakemistossa C-lähdetiedostona.
    • Käyttää suhteellinen polku joka on vain tiedostonimi ja tunniste, kun olet työskentelevät samassa hakemistossa C-lähdetiedostona.
  • liput: Sitä käytetään määrittämään, kuinka haluat avata tiedoston. Voimme käyttää seuraavia lippuja.

Liput

Kuvaus

O_RDONLY Avaa tiedoston vain luku -tilassa.
O_WRONLY Avaa tiedoston vain kirjoitustilassa.
O_RDWR Avaa tiedoston luku- ja kirjoitustilassa.
O_CREATE Luo tiedosto, jos sitä ei ole olemassa.
O_EXCL Estä luominen, jos se on jo olemassa.
O_ LISÄÄ Avaa tiedoston ja asettaa kohdistimen sisällön loppuun.
O_ASYNC Ota tulon ja lähdön ohjaus käyttöön signaalilla.
O_CLOEXEC Ota close-on-exec-tila käyttöön avoimessa tiedostossa.
O_NONBLOCK Poistaa avatun tiedoston eston käytöstä.
O_TMPFILE Luo nimetön väliaikainen tiedosto määritettyyn polkuun.

Kuinka C open() toimii käyttöjärjestelmässä

  • Etsi olemassa oleva tiedosto levyltä.
  • Luo tiedostotaulukkomerkintä.
  • Aseta ensimmäinen käyttämätön tiedostokuvaaja osoittamaan tiedostotaulukon merkintää.
  • Palautustiedoston kuvaaja käytetty, -1 epäonnistuessa.

Esimerkki C open()

C

kytkinkotelo java




// 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;> }>

>

>

Lähtö

fd = 3>

3. C sulkea

C:n close()-funktio kertoo käyttöjärjestelmälle, että tiedostokuvaaja on valmis, ja sulkee tiedostonkuvaajan osoittaman tiedoston. Se on määritelty sisällä otsikkotiedosto.

C:n close() syntaksi

int close(int fd);>

Parametri

  • fd: F ile sen tiedoston kuvaaja, jonka haluat sulkea.

Palautusarvo

  • 0 menestyksestä.
  • -1 virheen yhteydessä.

Kuinka C close() toimii käyttöjärjestelmässä

  • Tuhoa tiedostotaulukkomerkintä, johon viitataan tiedostokuvaustaulukon elementillä fd
    – Niin kauan kuin mikään muu prosessi ei viittaa siihen!
  • Aseta tiedostokuvaustaulukon elementtiin fd TYHJÄ

Esimerkki 1: close() C:ssä

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. '>);> }>

>

>

Lähtö

opened the fd = 3 closed the fd.>

Esimerkki 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);> }>

>

>

Lähtö

fd2 = 3>

Tässä tässä koodissa first open() palauttaa 3 koska kun pääprosessi luodaan, niin fd 0, 1, 2 ovat jo otettuja stdin , stdout, ja stderr . Joten ensimmäinen käyttämätön tiedostokuvaaja on 3 tiedostokuvaustaulukossa. Sen jälkeen close()-järjestelmässä puhelu on ilmaista 3 tiedostokuvaajat ja aseta sitten 3 tiedostokuvaajat kuten tyhjä . Joten kun kutsuimme toista open(), niin ensimmäinen käyttämätön fd on myös 3 . Joten tämän ohjelman tulos on 3 .

4. C-luku

Tiedostokuvaajalla fd osoittamasta tiedostosta read()-funktio lukee määritetyn määrän tavuja cnt syöttää muistialueelle, joka on merkitty buf . Onnistunut luku() päivittää tiedoston käyttöajan. Read()-funktio määritellään myös otsikkotiedoston sisällä.

Read()-funktion syntaksi C:ssä

size_t   read   (int   fd  , void*   buf  , size_t   cnt  );>

Parametrit

  • fd: sen tiedoston kuvaaja, josta tiedot luetaan.
  • buf: puskuri tietojen lukemista varten
  • cnt: puskurin pituus

Palautusarvo

  • return Onnistumisen yhteydessä luettujen tavujen määrä
  • palauttaa 0, kun saavut tiedoston loppuun
  • palauttaa -1 virheestä
  • paluu -1 signaalin keskeytyksessä

Tärkeitä kohtia

  • buf on osoitettava kelvolliseen muistipaikkaan, jonka pituus ei ole määritettyä kokoa pienempi ylivuodon vuoksi.
  • fd pitäisi olla kelvollinen tiedostokuvaaja, joka palautetaan open():stä lukutoiminnon suorittamiseksi, koska jos fd on NULL, lukemisen pitäisi tuottaa virhe.
  • cnt on pyydetty luettujen tavujen määrä, kun taas palautusarvo on luettujen tavujen todellinen määrä. Myös joskus luetun järjestelmäkutsun pitäisi lukea vähemmän tavuja kuin cnt.

Esimerkki read():stä C:ssä

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;> }>

>

>

Lähtö

called read(3, c, 10). returned that 10 bytes were read. Those bytes are as follows: 0 0 0 foo.>

Oletetaan, että foobar.txt koostuu 6 ASCII-merkistä foobar. Mikä sitten on seuraavan ohjelman tulos?

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);> }>

>

>

Lähtö

c = f>

Kuvaajat fd1 ja fd2 jokaisella on oma avoin tiedostotaulukkomerkintä, joten jokaisella kuvaajalla on oma tiedostopaikkansa foobar.txt . Näin ollen luettava fd2 lukee ensimmäisen tavun foobar.txt , ja tulos on c = f , ei c = o .

5. C-kirjoitus

Kirjoittaa cnt-tavuja bufista tiedostoon tai liittimeen, joka liittyy fd:hen. cnt ei saa olla suurempi kuin INT_MAX (määritetty limits.h-otsikkotiedostossa). Jos cnt on nolla, write() palauttaa yksinkertaisesti 0:n yrittämättä mitään muuta.

Write() on myös määritelty sisällä otsikkotiedosto.

Write()-funktion syntaksi C:ssä

size_t   write   (int   fd  , void*   buf  , size_t   cnt  );>

Parametrit

  • fd: tiedostokuvaaja
  • buf: puskuri, josta tietoja kirjoitetaan.
  • cnt: puskurin pituus.

Palautusarvo

  • palauttaa onnistumisesta kirjoitettujen tavujen määrän.
  • palauttaa 0, kun saavut tiedoston loppuun.
  • palauttaa -1 virheestä.
  • paluu -1 signaalin keskeytyksissä.

Tärkeitä kohtia C-kirjoituksesta

  • Tiedosto on avattava kirjoitustoimintoja varten
  • buf on oltava vähintään yhtä pitkä kuin cnt:n määrittelemä, koska jos buf-koko on pienempi kuin cnt, buf johtaa ylivuotoehtoon.
  • cnt on pyydetty kirjoitettavien tavujen määrä, kun taas palautusarvo on kirjoitettujen tavujen todellinen määrä. Tämä tapahtuu, kun fd siinä on vähemmän kirjoitettavia tavuja kuin cnt.
  • Jos signaali keskeyttää write():n, vaikutus on jokin seuraavista:
    • Jos write() ei ole vielä kirjoittanut mitään dataa, se palauttaa -1 ja asettaa errno arvoon EINTR.
    • Jos write() on onnistuneesti kirjoittanut joitakin tietoja, se palauttaa ennen keskeytystä kirjoittamansa tavumäärän.

Esimerkki write():stä C:ssä

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);> }>

Android-versiot

>

>

Lähtö

called write(3, 'hello geeks
', 12). it returned 11>

Täällä, kun näet tiedostossa foo.txt koodin suorittamisen jälkeen, saat a hei nörttejä . Jos foo.txt-tiedostossa on jo sisältöä, järjestelmäkutsut korvaavat sisällön ja kaikki aiempi sisältö on poistettu ja vain hei nörttejä sisältö on tiedostossa.

Esimerkki: Tulosta hello world ohjelmasta ilman printf-toimintoa.

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;> }>

>

>

Lähtö

hello world>

Tässä koodissa buf1-taulukon merkkijono Hei maailma kirjoitetaan ensin stdiniin fd[0] ja sen jälkeen tämä merkkijono kirjoitetaan stdiniin buf2-taulukkoon. Tämän jälkeen kirjoita buf2-taulukkoon stdout ja tulosta tulos Hei maailma .