Input-out-system anropar i C | Skapa, Öppna, Stäng, Läs, Skriv

Input-out-system anropar i C | Skapa, Öppna, Stäng, Läs, Skriv

Systemanrop är de anrop som ett program gör till systemkärnan för att tillhandahålla de tjänster som programmet inte har direkt åtkomst till. Till exempel ge tillgång till in- och utdataenheter som monitorer och tangentbord. Vi kan använda olika funktioner som tillhandahålls i programmeringsspråket C för in-/utdatasystemanrop som skapa, öppna, läsa, skriva, etc.

Innan vi går vidare till I/O-systemsamtal måste vi känna till några viktiga termer.

Viktig terminologi

Vad är filbeskrivningen?

Filbeskrivningen är ett heltal som unikt identifierar en öppen fil i processen.

Filbeskrivningstabell: En fil deskriptortabell är samlingen av heltalsmatrisindex som är fildeskriptorer där element är pekare till filtabellposter. En unik filbeskrivningstabell tillhandahålls i operativsystemet för varje process.

Filtabellpost: Filtabellposter är en struktur i minnets surrogat för en öppen fil, som skapas när en begäran om att öppna filen behandlas och dessa poster bibehåller filpositionen.

Filtabellpost i C

Standardfilbeskrivningar : När någon process startar, öppnas den processfilbeskrivningstabellens fd(filbeskrivning) 0, 1, 2 automatiskt, (som standard) var och en av dessa 3 fd refererar till filtabellposten för en fil med namnet /dev/tty

/dev/tty : In-memory surrogat för terminalen.

Terminal : Kombination av tangentbord/videoskärm.

Standardfilbeskrivningar

Läs från stdin => läs från fd 0 : När vi skriver något tecken från tangentbordet läser det från stdin till fd 0 och sparas till en fil som heter /dev/tty.
Skriv till stdout => skriv till fd 1 : När vi ser någon utdata till videoskärmen är den från filen som heter /dev/tty och skriven till stdout på skärmen genom fd 1.
Skriv till stderr => skriv till fd 2 : Vi ser något fel på videoskärmen, det är också från den filen att skriva till stderr på skärmen genom fd 2.

In-/utgångssystemanrop

I grund och botten finns det totalt 5 typer av I/O-systemanrop:

1. C skapa

Create()-funktionen används för att skapa en ny tom fil i C. Vi kan ange behörigheten och namnet på filen som vi vill skapa med funktionen create(). Det är definierat inuti header-filen och flaggorna som skickas som argument definieras inuti header-fil.

Syntax för create() i C

int   create  (char *  filename  , mode_t   mode  ); 

Parameter

  • filnamn: namnet på filen som du vill skapa
  • läge: indikerar behörigheter för den nya filen.

Returvärde

  • returnera den första oanvända filbeskrivningen (vanligtvis 3 när du först skapar användning i processen eftersom 0, 1, 2 fd är reserverade)
  • returnera -1 vid ett fel

Hur C create() fungerar i OS

  • Skapa en ny tom fil på disken.
  • Skapa filtabellpost.
  • Ställ in den första oanvända filbeskrivningen så att den pekar på filtabellposten.
  • Returnera filbeskrivning som används, -1 vid fel.

2. C öppen

Open()-funktionen i C används för att öppna filen för läsning, skrivning eller båda. Det är också kapabelt att skapa filen om den inte finns. Det är definierat inuti header-filen och flaggorna som skickas som argument definieras inuti header-fil.

Syntax för open() i C

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

Parametrar

  • Väg: Sökväg till filen som vi vill öppna.
    • Använd absolut väg börjar med / när du är inte arbetar i samma katalog som C-källfil.
    • Använda sig av relativ väg som bara är filnamnet med filändelse, när du är det arbetar i samma katalog som C-källfil.
  • flaggor: Den används för att ange hur du vill öppna filen. Vi kan använda följande flaggor.

Flaggor

Beskrivning

O_RDONLY Öppnar filen i skrivskyddat läge.
O_FULLT Öppnar filen i skrivskyddsläge.
O_RDWR Öppnar filen i läs- och skrivläge.
O_SKAPA Skapa en fil om den inte finns.
O_EXCL Förhindra skapandet om det redan finns.
O_ BILAGA Öppnar filen och placerar markören i slutet av innehållet.
O_ASYNC Aktivera in- och utgångsstyrning via signal.
O_CLOEXEC Aktivera close-on-exec-läge på den öppna filen.
O_NONBLOCK Inaktiverar blockering av den öppnade filen.
O_TMPFILE Skapa en icke namngiven temporär fil på den angivna sökvägen.

Hur C open() fungerar i OS

  • Hitta den befintliga filen på disken.
  • Skapa filtabellpost.
  • Ställ in den första oanvända filbeskrivningen så att den pekar på filtabellposten.
  • Returnera filbeskrivning som används, -1 vid fel.

Exempel på 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;> }>

Produktion

fd = 3 

3. C stäng

Close()-funktionen i C talar om för operativsystemet att du är klar med en filbeskrivning och stänger filen som pekas av filbeskrivningen. Det är definierat inuti header-fil.

Syntax för close() i C

int close(int fd); 

Parameter

  • fd: F ile-beskrivning för filen som du vill stänga.

Returvärde

  • 0 på framgång.
  • -1 på fel.

Hur C close() fungerar i operativsystemet

  • Förstör filtabellpost som refereras av element fd i filbeskrivningstabellen
    – Så länge ingen annan process pekar på det!
  • Ställ in element fd i filbeskrivningstabellen till NULL

Exempel 1: close() i 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. '> );> }>

Produktion

opened the fd = 3 closed the fd. 

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

Produktion

fd2 = 3 

Här, I denna kod returnerar first open() 3 för när huvudprocessen skapas, då fd 0, 1, 2 är redan tagna av stdin , stdout, och stderr . Så den första oanvända filbeskrivningen är 3 i filbeskrivningstabellen. Efter att i close() systemanrop är gratis det dessa 3 filbeskrivningar och ställ sedan in 3 filbeskrivningar som null . Så när vi anropade den andra open(), så är den första oanvända fd också 3 . Så resultatet av detta program är 3 .

4. C läs

Från filen som anges av filbeskrivningen fd, läser read()-funktionen det angivna antalet byte cnt inmatning i minnesområdet som indikeras av buff . En framgångsrik read() uppdaterar åtkomsttiden för filen. Read()-funktionen är också definierad i rubrikfilen.

Syntax för read() i C

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

Parametrar

  • fd: filbeskrivning av filen från vilken data ska läsas.
  • buff: buffert att läsa data från
  • cnt: buffertens längd

Returvärde

  • return Antal byte lästa vid framgång
  • returnera 0 när du når slutet av filen
  • returnera -1 vid fel
  • retur -1 vid signalavbrott

Viktiga punkter

  • buff måste peka på en giltig minnesplats med en längd som inte är mindre än den angivna storleken på grund av spill.
  • fd bör vara en giltig filbeskrivning som returneras från open() för att utföra läsoperationen eftersom om fd är NULL bör läsningen generera ett fel.
  • cnt är det begärda antalet lästa byte, medan returvärdet är det faktiska antalet lästa byte. Vissa gånger bör också läsa systemanrop läsa färre byte än cnt.

Exempel på read() i 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;> }>

Produktion

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

Anta att foobar.txt består av de 6 ASCII-tecken foobar. Vad är då resultatet av följande program?

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

Produktion

c = f 

Beskrivningarna fd1 och fd2 var och en har sin egen öppna filtabellpost, så varje deskriptor har sin egen filposition för foobar.txt . Alltså läser från fd2 läser den första byten av foobar.txt , och utgången är c = f , inte c = o .

5. C skriv

Skriver cnt-bytes från buf till filen eller socket som är associerad med fd. cnt bör inte vara större än INT_MAX (definierad i rubrikfilen limits.h). Om cnt är noll, returnerar write() helt enkelt 0 utan att försöka göra någon annan åtgärd.

Write() är också definierad inuti header-fil.

Syntax för write() i C

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

Parametrar

  • fd: filbeskrivning
  • buff: buffert att skriva data från.
  • cnt: buffertens längd.

Returvärde

  • returnerar antalet byte som skrivits vid framgång.
  • returnera 0 när du når slutet av filen.
  • returnera -1 vid fel.
  • retur -1 på signalavbrott.

Viktiga punkter om C write

  • Filen måste öppnas för skrivoperationer
  • buff måste vara minst så lång som specificerats av cnt eftersom om bufstorleken är mindre än cnt så kommer buf att leda till överflödestillståndet.
  • cnt är det begärda antalet byte att skriva, medan returvärdet är det faktiska antalet skrivna byte. Detta händer när fd har ett mindre antal byte att skriva än cnt.
  • Om write() avbryts av en signal är effekten en av följande:
    • Om write() inte har skrivit någon data ännu, returnerar den -1 och sätter errno till EINTR.
    • Om write() har lyckats skriva en del data, returnerar den antalet byte den skrev innan den avbröts.

Exempel på write() i 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);> }>

Produktion

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

Här, när du ser i filen foo.txt efter att ha kört koden, får du en hej nördar . Om foo.txt-filen redan har en del innehåll i den så skriver ett systemanrop över innehållet och allt tidigare innehåll är raderade och bara hej nördar innehållet kommer att ha i filen.

Exempel: Skriv ut hello world från programmet utan att använda någon printf-funktion.

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

Produktion

hello world 

I den här koden, buf1 arrays sträng Hej världen skrivs först i stdin fd[0] och därefter skrivs den här strängen in i stdin till buf2-matrisen. Skriv sedan in i buf2-arrayen till stdout och skriv ut Hej världen .