logo

Eingabe-Ausgabe-Systemaufrufe in C | Erstellen, öffnen, schließen, lesen, schreiben

Systemaufrufe sind Aufrufe eines Programms an den Systemkernel, um Dienste bereitzustellen, auf die das Programm keinen direkten Zugriff hat. Beispielsweise Bereitstellung des Zugriffs auf Ein- und Ausgabegeräte wie Monitore und Tastaturen. Wir können verschiedene in der Programmiersprache C bereitgestellte Funktionen für Eingabe-/Ausgabe-Systemaufrufe wie Erstellen, Öffnen, Lesen, Schreiben usw. verwenden.

Bevor wir zu den I/O-Systemaufrufen übergehen, müssen wir einige wichtige Begriffe kennen.



Wichtige Terminologie

Was ist der Dateideskriptor?

Der Dateideskriptor ist eine Ganzzahl, die eine geöffnete Datei des Prozesses eindeutig identifiziert.

Dateideskriptortabelle: Eine Datei Die Deskriptortabelle ist die Sammlung ganzzahliger Array-Indizes, die Dateideskriptoren sind, in denen Elemente Zeiger auf Dateitabelleneinträge sind. Für jeden Prozess wird im Betriebssystem eine eindeutige Dateideskriptortabelle bereitgestellt.



Dateitabelleneintrag: Dateitabelleneinträge sind ein Struktur-In-Memory-Ersatz für eine geöffnete Datei, der bei der Verarbeitung einer Anforderung zum Öffnen der Datei erstellt wird und diese Einträge die Dateiposition beibehalten.

Dateitabelleneintrag in C

Standard-Dateideskriptoren : Wenn ein Prozess gestartet wird, wird der fd(Dateideskriptor) 0, 1, 2 dieser Prozessdateideskriptorentabelle automatisch geöffnet. (Standardmäßig) verweist jeder dieser 3 fd auf den Dateitabelleneintrag für eine Datei mit dem Namen /dev/tty



/dev/tty : Speicherinterner Ersatz für das Terminal.

Terminal : Kombination aus Tastatur und Videobildschirm.

Standard-Dateideskriptoren

Von stdin lesen => von fd 0 lesen : Immer wenn wir ein Zeichen über die Tastatur schreiben, liest es von stdin bis fd 0 und speichert es in einer Datei namens /dev/tty.
Auf stdout schreiben => auf fd 1 schreiben : Immer wenn wir eine Ausgabe auf dem Videobildschirm sehen, stammt diese aus der Datei mit dem Namen /dev/tty und wird über fd 1 nach stdout im Bildschirm geschrieben.
In stderr schreiben => in fd 2 schreiben : Wir sehen jeden Fehler auf dem Videobildschirm, es wird auch von dieser Datei über fd 2 nach stderr im Bildschirm geschrieben.

Eingabe-/Ausgabesystemaufrufe

Grundsätzlich gibt es insgesamt 5 Arten von I/O-Systemaufrufen:

1. C erstellen

Die Funktion create() wird verwendet, um eine neue leere Datei in C zu erstellen. Mit der Funktion create() können wir die Berechtigung und den Namen der Datei angeben, die wir erstellen möchten. Es ist im Inneren definiert Die Header-Datei und die Flags, die als Argumente übergeben werden, werden darin definiert Header-Datei.

Syntax von create() in C

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

Parameter

  • Dateiname: Name der Datei, die Sie erstellen möchten
  • Modus: Gibt die Berechtigungen der neuen Datei an.

Rückgabewert

  • Gibt den ersten nicht verwendeten Dateideskriptor zurück (im Allgemeinen 3, wenn er zum ersten Mal im Prozess verwendet wird, da 0, 1, 2 fd reserviert sind)
  • Gibt -1 zurück, wenn ein Fehler auftritt

Wie C create() im Betriebssystem funktioniert

  • Erstellen Sie eine neue leere Datei auf der Festplatte.
  • Dateitabelleneintrag erstellen.
  • Legen Sie den ersten nicht verwendeten Dateideskriptor so fest, dass er auf den Dateitabelleneintrag verweist.
  • Verwendeter Rückgabedateideskriptor, -1 bei Fehler.

2. C öffnen

Die Funktion open() in C wird verwendet, um die Datei zum Lesen, Schreiben oder beidem zu öffnen. Es ist auch in der Lage, die Datei zu erstellen, wenn sie nicht existiert. Es ist im Inneren definiert Die Header-Datei und die Flags, die als Argumente übergeben werden, werden darin definiert Header-Datei.

Java math.random

Syntax von open() in C

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

Parameter

  • Weg: Pfad zur Datei, die wir öffnen möchten.
    • Benutzen Sie die absoluter Pfad beginnend mit / wann du bist nicht im selben Verzeichnis arbeiten als C-Quelldatei.
    • Verwenden relativer Pfad Das ist nur der Dateiname mit Erweiterung, wenn Sie es sind im selben Verzeichnis arbeiten als C-Quelldatei.
  • Flaggen: Hiermit legen Sie fest, wie Sie die Datei öffnen möchten. Wir können die folgenden Flags verwenden.

Flaggen

Beschreibung

O_RDONLY Öffnet die Datei im schreibgeschützten Modus.
O_FALSCH Öffnet die Datei im schreibgeschützten Modus.
O_RDWR Öffnet die Datei im Lese- und Schreibmodus.
O_CREATE Erstellen Sie eine Datei, falls diese nicht vorhanden ist.
O_EXCL Verhindern Sie die Erstellung, wenn sie bereits vorhanden ist.
O_ APPEND Öffnet die Datei und platziert den Cursor am Ende des Inhalts.
O_ASYNC Aktivieren Sie die Eingangs- und Ausgangssteuerung per Signal.
O_CLOEXEC Aktivieren Sie den Close-on-Exec-Modus für die geöffnete Datei.
O_NONBLOCK Deaktiviert das Blockieren der geöffneten Datei.
O_TMPFILE Erstellen Sie eine unbenannte temporäre Datei im angegebenen Pfad.

Wie C open() im Betriebssystem funktioniert

  • Suchen Sie die vorhandene Datei auf der Festplatte.
  • Dateitabelleneintrag erstellen.
  • Legen Sie den ersten nicht verwendeten Dateideskriptor so fest, dass er auf den Dateitabelleneintrag verweist.
  • Verwendeter Rückgabedateideskriptor, -1 bei Fehler.

Beispiel für 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;> }>

>

>

Ausgabe

fd = 3>

3. C schließen

Die Funktion close() in C teilt dem Betriebssystem mit, dass Sie mit einem Dateideskriptor fertig sind, und schließt die Datei, auf die der Dateideskriptor verweist. Es ist im Inneren definiert Header-Datei.

Syntax von close() in C

int close(int fd);>

Parameter

  • fd: F Dateideskriptor der Datei, die Sie schließen möchten.

Rückgabewert

  • 0 auf Erfolg.
  • -1 auf Fehler.

Wie C close() im Betriebssystem funktioniert

  • Zerstöre den Dateitabelleneintrag, auf den durch das Element fd der Dateideskriptortabelle verwiesen wird
    – Solange kein anderer Prozess darauf verweist!
  • Setzen Sie das Element fd der Dateideskriptortabelle auf NULL

Beispiel 1: close() in C

C

Karten Java




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

>

>

Ausgabe

opened the fd = 3 closed the fd.>

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

>

>

Ausgabe

fd2 = 3>

Hier wird in diesem Code zuerst open() zurückgegeben 3 denn wenn der Hauptprozess erstellt wird, dann fd 0, 1, 2 sind bereits vergeben stdin , Standard, Und stderr . Der erste ungenutzte Dateideskriptor ist also 3 in der Dateideskriptortabelle. Danach werden diese im Systemaufruf close() freigegeben 3 Dateideskriptoren und dann festlegen 3 Dateideskriptoren als Null . Wenn wir also das zweite open() aufgerufen haben, ist auch das erste nicht verwendete fd vorhanden 3 . Die Ausgabe dieses Programms ist also 3 .

4. C lesen

Aus der durch den Dateideskriptor fd angegebenen Datei liest die Funktion read() die angegebene Anzahl an Bytes cnt der Eingabe in den mit gekennzeichneten Speicherbereich buf . Ein erfolgreicher read() aktualisiert die Zugriffszeit für die Datei. Die Funktion read() ist ebenfalls in der Header-Datei definiert.

Syntax von read() in C

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

Parameter

  • fd: Dateideskriptor der Datei, aus der Daten gelesen werden sollen.
  • Buff: Puffer, aus dem Daten gelesen werden sollen
  • cnt: Länge des Puffers

Rückgabewert

  • return Anzahl der bei Erfolg gelesenen Bytes
  • Gibt 0 zurück, wenn das Ende der Datei erreicht ist
  • Gibt bei Fehler -1 zurück
  • Gibt -1 bei Signalunterbrechung zurück

Wichtige Punkte

  • buf muss aufgrund eines Überlaufs auf einen gültigen Speicherort mit einer Länge verweisen, die nicht kleiner als die angegebene Größe ist.
  • fd sollte ein gültiger Dateideskriptor sein, der von open() zurückgegeben wird, um den Lesevorgang auszuführen, denn wenn fd NULL ist, sollte der Lesevorgang einen Fehler erzeugen.
  • cnt ist die angeforderte Anzahl der gelesenen Bytes, während der Rückgabewert die tatsächliche Anzahl der gelesenen Bytes ist. Außerdem sollte der Systemaufruf read manchmal weniger Bytes lesen als cnt.

Beispiel für read() in C

C




abstrakte Klasse Java

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

>

Palindromzahl

>

Ausgabe

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

Angenommen, foobar.txt besteht aus den 6 ASCII-Zeichen foobar. Was ist dann die Ausgabe des folgenden Programms?

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

>

>

Ausgabe

c = f>

Die Deskriptoren fd1 Und fd2 Jeder Deskriptor hat seinen eigenen offenen Dateitabelleneintrag, sodass jeder Deskriptor seine eigene Dateiposition für hat foobar.txt . So lautet die Lektüre fd2 liest das erste Byte von foobar.txt , und die Ausgabe ist c = f , nicht c = o .

5. C schreiben

Schreibt cnt Bytes von buf in die mit fd verknüpfte Datei oder den Socket. cnt sollte nicht größer als INT_MAX sein (definiert in der Header-Datei limits.h). Wenn cnt Null ist, gibt write() einfach 0 zurück, ohne eine andere Aktion zu versuchen.

Das write() ist ebenfalls darin definiert Header-Datei.

Syntax von write() in C

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

Parameter

  • fd: Dateideskriptor
  • Buff: Puffer, aus dem Daten geschrieben werden sollen.
  • cnt: Länge des Puffers.

Rückgabewert

  • Gibt die Anzahl der geschriebenen Bytes bei Erfolg zurück.
  • Gibt 0 zurück, wenn das Ende der Datei erreicht ist.
  • Gibt bei Fehler -1 zurück.
  • Gibt -1 bei Signalunterbrechungen zurück.

Wichtige Punkte zum Schreiben in C

  • Für Schreibvorgänge muss die Datei geöffnet werden
  • buf muss mindestens so lang sein, wie durch cnt angegeben, denn wenn die Buff-Größe kleiner als cnt ist, führt buf zum Überlaufzustand.
  • cnt ist die angeforderte Anzahl der zu schreibenden Bytes, während der Rückgabewert die tatsächliche Anzahl der geschriebenen Bytes ist. Dies geschieht, wenn fd hat eine geringere Anzahl zu schreibender Bytes als cnt.
  • Wenn write() durch ein Signal unterbrochen wird, hat dies eine der folgenden Auswirkungen:
    • Wenn write() noch keine Daten geschrieben hat, gibt es -1 zurück und setzt errno auf EINTR.
    • Wenn write() einige Daten erfolgreich geschrieben hat, gibt es die Anzahl der Bytes zurück, die es vor der Unterbrechung geschrieben hat.

Beispiel für write() in 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);> }>

>

>

Ausgabe

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

Wenn Sie hier nach dem Ausführen des Codes in der Datei foo.txt sehen, erhalten Sie eine Hallo Geeks . Wenn die Datei foo.txt bereits Inhalt enthält, überschreiben die Systemaufrufe write a den Inhalt und alle vorherigen Inhalte werden gelöscht gelöscht und nur Hallo Geeks Der Inhalt wird in der Datei enthalten sein.

Beispiel: Drucken Sie „Hallo Welt“ aus dem Programm, ohne eine printf-Funktion zu verwenden.

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

ipconfig für Ubuntu
>

>

Ausgabe

hello world>

In diesem Code die Zeichenfolge des buf1-Arrays Hallo Welt wird zuerst in stdin fd[0] geschrieben, danach wird dieser String in stdin in das buf2-Array geschrieben. Danach in das buf2-Array in die stdout-Ausgabe schreiben und die Ausgabe drucken Hallo Welt .