Vstupně-výstupní systémová volání v C | Vytvořit, otevřít, zavřít, číst, psát

Vstupně-výstupní systémová volání v C | Vytvořit, otevřít, zavřít, číst, psát

Systémová volání jsou volání, která program provádí do jádra systému, aby poskytoval služby, ke kterým nemá program přímý přístup. Například poskytování přístupu ke vstupním a výstupním zařízením, jako jsou monitory a klávesnice. Můžeme použít různé funkce poskytované v programovacím jazyce C pro vstupní/výstupní systémová volání, jako je vytvoření, otevření, čtení, zápis atd.

Než přejdeme k I/O systémovým voláním, potřebujeme vědět o několika důležitých pojmech.

Důležitá terminologie

Co je to deskriptor souboru?

Deskriptor souboru je celé číslo, které jednoznačně identifikuje otevřený soubor procesu.

Tabulka deskriptoru souboru: Soubor tabulka deskriptorů je kolekce indexů celočíselného pole, které jsou deskriptory souborů, ve kterých jsou prvky ukazatele na položky tabulky souborů. Pro každý proces je v operačním systému k dispozici jedna jedinečná tabulka deskriptorů souborů.

Záznam v tabulce souborů: Záznamy tabulky souborů jsou náhradou struktury v paměti pro otevřený soubor, která se vytvoří při zpracování požadavku na otevření souboru a tyto záznamy udrží pozici souboru.

Záznam tabulky souborů v C

Standardní deskriptory souborů : Když se spustí jakýkoli proces, pak se automaticky otevře tabulka deskriptorů souboru procesu fd(deskriptor souboru) 0, 1, 2, (ve výchozím nastavení) každý z těchto 3 fd odkazuje na položku tabulky souborů pro soubor s názvem /dev/tty

/dev/tty : Náhrada terminálu v paměti.

Terminál : Kombinovaná klávesnice/obrazovka videa.

Standardní deskriptory souborů

Číst ze stdin => číst z fd 0 : Kdykoli napíšeme jakýkoli znak z klávesnice, přečte se od stdin po fd 0 a uloží se do souboru s názvem /dev/tty.
Zapsat na stdout => zapsat na fd 1 : Kdykoli vidíme jakýkoli výstup na obrazovku videa, pochází ze souboru s názvem /dev/tty a zapisuje se do stdout na obrazovce přes fd 1.
Zapsat do stderr => zapsat do fd 2 : Vidíme jakoukoli chybu na obrazovce videa, je to také z tohoto souboru zápis do stderr na obrazovce přes fd 2.

Vstupní/výstupní systémová volání

V zásadě existuje celkem 5 typů I/O systémových volání:

1. C vytvořit

Funkce create() slouží k vytvoření nového prázdného souboru v C. Pomocí funkce create() můžeme zadat oprávnění a název souboru, který chceme vytvořit. Je definován uvnitř hlavičkový soubor a příznaky, které jsou předány jako argumenty, jsou definovány uvnitř hlavičkový soubor.

Syntaxe create() v C

int   create  (char *  filename  , mode_t   mode  ); 

Parametr

  • název souboru: název souboru, který chcete vytvořit
  • režim: označuje oprávnění nového souboru.

Návratová hodnota

  • vrátit první nepoužitý deskriptor souboru (obecně 3 při prvním vytvoření použití v procesu, protože 0, 1, 2 fd jsou vyhrazeny)
  • vrátí -1 při chybě

Jak C create() funguje v OS

  • Vytvořte nový prázdný soubor na disku.
  • Vytvořte záznam v tabulce souborů.
  • Nastavte první nepoužitý deskriptor souboru tak, aby ukazoval na položku tabulky souborů.
  • Vraťte použitý deskriptor souboru, -1 při selhání.

2. C otevřít

Funkce open() v C se používá k otevření souboru pro čtení, zápis nebo obojí. Je také schopen vytvořit soubor, pokud neexistuje. Je definován uvnitř hlavičkový soubor a příznaky, které jsou předány jako argumenty, jsou definovány uvnitř hlavičkový soubor.

Syntaxe open() v C

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

Parametry

  • Cesta: Cesta k souboru, který chceme otevřít.
    • Použijte absolutní cesta začínající na / když jste ne pracující ve stejném adresáři jako zdrojový soubor C.
    • Použití relativní cesta což je pouze název souboru s příponou, když jste pracující ve stejném adresáři jako zdrojový soubor C.
  • vlajky: Používá se k určení, jak chcete soubor otevřít. Můžeme použít následující příznaky.

Vlajky

Popis

O_RDONLY Otevře soubor v režimu pouze pro čtení.
O_WRONLY Otevře soubor v režimu pouze pro zápis.
O_RDWR Otevře soubor v režimu čtení a zápisu.
O_CREATE Vytvořte soubor, pokud neexistuje.
O_EXCL Zabránit vytvoření, pokud již existuje.
O_ PŘILOŽIT Otevře soubor a umístí kurzor na konec obsahu.
O_ASYNC Povolit ovládání vstupu a výstupu signálem.
O_CLOEXEC Povolte u otevřeného souboru režim close-on-exec.
O_NONBLOCK Zakáže blokování otevřeného souboru.
O_TMPFILE Vytvořte nepojmenovaný dočasný soubor v zadané cestě.

Jak C open() funguje v OS

  • Najděte existující soubor na disku.
  • Vytvořte záznam v tabulce souborů.
  • Nastavte první nepoužitý deskriptor souboru tak, aby ukazoval na položku tabulky souborů.
  • Vraťte použitý deskriptor souboru, -1 při selhání.

Příklad 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;> }>

Výstup

fd = 3 

3. C zavřít

Funkce close() v C sdělí operačnímu systému, že jste skončili s deskriptorem souboru, a zavře soubor, na který ukazuje deskriptor souboru. Je definován uvnitř hlavičkový soubor.

Syntaxe close() v C

int close(int fd); 

Parametr

  • fd: F ile deskriptor souboru, který chcete zavřít.

Návratová hodnota

  • 0 na úspěchu.
  • -1 na chybu.

Jak C close() funguje v OS

  • Zničte záznam tabulky souborů, na který odkazuje prvek fd tabulky deskriptorů souborů
    – Dokud na to neukazuje žádný jiný proces!
  • Nastavit prvek fd tabulky deskriptoru souboru na NULA

Příklad 1: close() v 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. '> );> }>

Výstup

opened the fd = 3 closed the fd. 

Příklad 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);> }>

Výstup

fd2 = 3 

Zde se v tomto kódu nejprve vrátí open(). 3 protože když je vytvořen hlavní proces, pak fd 0, 1, 2 jsou již obsazeny stdin , stdout, a stderr . Takže první nepoužitý deskriptor souboru je 3 v tabulce deskriptorů souborů. Poté je v close() systémové volání zdarma 3 deskriptory souborů a poté nastavte 3 deskriptory souborů jako nula . Takže když jsme zavolali druhé open(), pak je také první nepoužité fd 3 . Takže výstupem tohoto programu je 3 .

4. C číst

Ze souboru označeného deskriptorem souboru fd přečte funkce read() zadané množství bajtů cnt vstupu do oblasti paměti označené buf . Úspěšné read() aktualizuje čas přístupu k souboru. Funkce read() je také definována uvnitř hlavičkového souboru.

Syntaxe read() v C

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

Parametry

  • fd: deskriptor souboru souboru, ze kterého se mají číst data.
  • buf: vyrovnávací paměti pro čtení dat
  • cnt: délka vyrovnávací paměti

Návratová hodnota

  • return Počet bajtů přečtených při úspěchu
  • vrátí 0 po dosažení konce souboru
  • návrat -1 při chybě
  • návrat -1 při přerušení signálu

Důležité body

  • buf potřebuje ukazovat na platné paměťové místo s délkou ne menší než zadaná velikost z důvodu přetečení.
  • fd by měl být platný deskriptor souboru vrácený z open() k provedení operace čtení, protože pokud je fd NULL, čtení by mělo vygenerovat chybu.
  • cnt je požadovaný počet přečtených bajtů, zatímco návratová hodnota je skutečný počet přečtených bajtů. Někdy by také čtené systémové volání mělo číst méně bajtů než cnt.

Příklad read() v 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;> }>

Výstup

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

Předpokládejme, že foobar.txt se skládá ze 6 ASCII znaků foobar. Jaký je tedy výstup následujícího programu?

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

Výstup

c = f 

Deskriptory fd1 a fd2 každý má svůj vlastní otevřený záznam v tabulce souborů, takže každý deskriptor má svou vlastní pozici souboru foobar.txt . Tedy čtení z fd2 přečte první bajt foobar.txt a výstupem je c = f , ne c = o .

5. C psát

Zapíše cnt bajtů z buf do souboru nebo soketu spojeného s fd. cnt by nemělo být větší než INT_MAX (definováno v hlavičkovém souboru limited.h). Pokud je cnt nula, write() jednoduše vrátí 0, aniž by se pokusil o jakoukoli jinou akci.

Uvnitř je také definován write(). hlavičkový soubor.

Syntaxe write() v C

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

Parametry

  • fd: deskriptor souboru
  • buf: vyrovnávací paměti pro zápis dat.
  • cnt: délka vyrovnávací paměti.

Návratová hodnota

  • vrátí počet bajtů zapsaných při úspěchu.
  • vrátí 0 po dosažení konce souboru.
  • návrat -1 při chybě.
  • návrat -1 při přerušení signálu.

Důležité body o zápisu C

  • Pro operace zápisu je třeba soubor otevřít
  • buf musí být alespoň tak dlouhé, jak je specifikováno u cnt, protože pokud je velikost buf menší než cnt, buf povede ke stavu přetečení.
  • cnt je požadovaný počet bajtů k zápisu, zatímco návratová hodnota je skutečný počet zapsaných bajtů. To se stane, když fd má menší počet bajtů k zápisu než cnt.
  • Pokud je write() přerušeno signálem, efekt je jeden z následujících:
    • Pokud write() ještě nezapsala žádná data, vrátí -1 a nastaví errno na EINTR.
    • Pokud funkce write() úspěšně zapsala některá data, vrátí počet bajtů, které zapsala, než byla přerušena.

Příklad write() v 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);> }>

Výstup

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

Zde, když po spuštění kódu uvidíte v souboru foo.txt, dostanete a ahoj geekové . Pokud soubor foo.txt již má nějaký obsah, pak systémová volání write a přepíší obsah a veškerý předchozí obsah je smazáno a jen ahoj geekové obsah bude mít v souboru.

Příklad: Tisk ahoj světe z programu bez použití funkce 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;> }>

Výstup

hello world 

V tomto kódu řetězec buf1 pole Ahoj světe je nejprve zapsán do stdin fd[0] a poté se tento řetězec zapíše do stdin do pole buf2. Poté zapište do pole buf2 na stdout a vytiskněte výstup Ahoj světe .