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.

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.

Čí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.
'>);> }> |
řazení java arraylist
>
>
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 .