logo

Appels système d'entrée-sortie en C | Créer, ouvrir, fermer, lire, écrire

Les appels système sont les appels qu'un programme effectue au noyau du système pour fournir les services auxquels le programme n'a pas d'accès direct. Par exemple, donner accès à des périphériques d'entrée et de sortie tels que des moniteurs et des claviers. Nous pouvons utiliser diverses fonctions fournies dans le langage de programmation C pour les appels système d'entrée/sortie tels que créer, ouvrir, lire, écrire, etc.

Avant de passer aux appels système d'E/S, nous devons connaître quelques termes importants.



Terminologie importante

Qu'est-ce que le descripteur de fichier ?

Le descripteur de fichier est un entier qui identifie de manière unique un fichier ouvert du processus.

Table de descripteur de fichier : un fichier La table de descripteurs est la collection d'indices de tableaux d'entiers qui sont des descripteurs de fichiers dans lesquels les éléments sont des pointeurs vers les entrées de la table de fichiers. Un tableau de descripteurs de fichiers unique est fourni dans le système d'exploitation pour chaque processus.



Entrée de la table des fichiers : Les entrées de la table de fichiers sont une structure de substitution en mémoire pour un fichier ouvert, qui est créée lors du traitement d'une demande d'ouverture du fichier et ces entrées conservent la position du fichier.

Entrée de table de fichiers en C

Descripteurs de fichiers standard : Lorsqu'un processus démarre, alors le fd (descripteur de fichier) 0, 1, 2 de la table de descripteurs de fichier de ce processus s'ouvre automatiquement, (par défaut) chacune de ces 3 entrées de table de fichier de références fd pour un fichier nommé /dev/tty



/dev/tty : substitut en mémoire pour le terminal.

Terminal : Combinaison clavier/écran vidéo.

Descripteurs de fichiers standard

Lire depuis stdin => lire depuis fd 0 : Chaque fois que nous écrivons un caractère à partir du clavier, il lit depuis stdin jusqu'à fd 0 et l'enregistre dans un fichier nommé /dev/tty.
Écrire sur stdout => écrire sur fd 1 : Chaque fois que nous voyons une sortie sur l'écran vidéo, elle provient du fichier nommé /dev/tty et écrit sur la sortie standard de l'écran via fd 1.
Écrire sur stderr => écrire sur fd 2 : Nous voyons une erreur sur l'écran vidéo, c'est également à partir de ce fichier que nous écrivons sur stderr à l'écran via fd 2.

Appels système d’entrée/sortie

Fondamentalement, il existe au total 5 types d’appels système d’E/S :

1. C créer

La fonction create() est utilisée pour créer un nouveau fichier vide en C. Nous pouvons spécifier l'autorisation et le nom du fichier que nous voulons créer à l'aide de la fonction create(). Il est défini à l'intérieur fichier d'en-tête et les indicateurs passés en arguments sont définis à l'intérieur En tête de fichier.

Syntaxe de create() en C

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

Paramètre

  • nom de fichier: nom du fichier que vous souhaitez créer
  • mode: indique les autorisations du nouveau fichier.

Valeur de retour

  • renvoie le premier descripteur de fichier inutilisé (généralement 3 lors de la première création d'utilisation dans le processus car 0, 1, 2 fd sont réservés)
  • renvoie -1 en cas d'erreur

Comment fonctionne C create() dans le système d'exploitation

  • Créez un nouveau fichier vide sur le disque.
  • Créez une entrée de table de fichiers.
  • Définissez le premier descripteur de fichier inutilisé pour qu'il pointe vers l'entrée de la table de fichiers.
  • Renvoie le descripteur de fichier utilisé, -1 en cas d'échec.

2. C ouvert

La fonction open() en C est utilisée pour ouvrir le fichier en lecture, en écriture ou les deux. Il est également capable de créer le fichier s'il n'existe pas. Il est défini à l'intérieur fichier d'en-tête et les indicateurs passés en arguments sont définis à l'intérieur En tête de fichier.

Syntaxe de open() en C

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

Paramètres

  • Chemin: Chemin d'accès au fichier que nous voulons ouvrir.
    • Utilisez le chemin absolu en commençant par / quand tu es pas travailler dans le même répertoire comme fichier source C.
    • Utiliser chemin relatif qui est uniquement le nom du fichier avec l'extension, lorsque vous êtes travailler dans le même répertoire comme fichier source C.
  • drapeaux : Il est utilisé pour spécifier comment vous souhaitez ouvrir le fichier. Nous pouvons utiliser les drapeaux suivants.

Drapeaux

instruction de commutation java

Description

O_RDONLY Ouvre le fichier en mode lecture seule.
O_WRONLY Ouvre le fichier en mode écriture seule.
O_RDWR Ouvre le fichier en mode lecture et écriture.
O_CRÉER Créez un fichier s'il n'existe pas.
O_EXCL Empêcher la création si elle existe déjà.
O_ AJOUTER Ouvre le fichier et place le curseur à la fin du contenu.
O_ASYNC Activer le contrôle d’entrée et de sortie par signal.
O_CLOEXEC Activez le mode de fermeture après exécution sur le fichier ouvert.
O_NONBLOC Désactive le blocage du fichier ouvert.
O_TMPFILE Créez un fichier temporaire sans nom au chemin spécifié.

Comment fonctionne C open() dans le système d'exploitation

  • Recherchez le fichier existant sur le disque.
  • Créez une entrée de table de fichiers.
  • Définissez le premier descripteur de fichier inutilisé pour qu'il pointe vers l'entrée de la table de fichiers.
  • Renvoie le descripteur de fichier utilisé, -1 en cas d'échec.

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

>

>

Sortir

fd = 3>

3. C fermer

La fonction close() en C indique au système d'exploitation que vous en avez terminé avec un descripteur de fichier et ferme le fichier pointé par le descripteur de fichier. Il est défini à l'intérieur En tête de fichier.

Syntaxe de close() en C

int close(int fd);>

Paramètre

  • fd: F descripteur de fichier du fichier que vous souhaitez fermer.

Valeur de retour

  • 0 sur le succès.
  • -1 sur erreur.

Comment fonctionne C close() dans le système d'exploitation

  • Détruire l'entrée de la table de fichiers référencée par l'élément fd de la table des descripteurs de fichiers
    – Tant qu’aucun autre processus ne le pointe !
  • Définissez l'élément fd de la table des descripteurs de fichiers sur NUL

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

>

>

Sortir

opened the fd = 3 closed the fd.>

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

>

>

Sortir

fd2 = 3>

Ici, dans ce code, open() renvoie d'abord 3 parce que lorsque le processus principal est créé, alors fd 0, 1, 2 sont déjà pris par entrée standard , sortie standard, et stderr . Le premier descripteur de fichier inutilisé est donc 3 dans la table des descripteurs de fichiers. Après cela, dans close(), l'appel système est gratuit. 3 descripteurs de fichiers, puis définissez 3 descripteurs de fichiers comme nul . Ainsi, lorsque nous avons appelé le deuxième open(), alors le premier fd inutilisé est également 3 . Ainsi, le résultat de ce programme est 3 .

4. C lire

A partir du fichier indiqué par le descripteur de fichier fd, la fonction read() lit le nombre d'octets spécifié cnt d'entrée dans la zone mémoire indiquée par bof . Un read() réussi met à jour le temps d’accès au fichier. La fonction read() est également définie dans le fichier d'en-tête.

Syntaxe de read() en C

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

Paramètres

  • fd: descripteur de fichier du fichier à partir duquel les données doivent être lues.
  • bouf : tampon pour lire les données
  • raison : longueur du tampon

Valeur de retour

  • return Nombre d'octets lus en cas de succès
  • renvoie 0 en arrivant à la fin du fichier
  • renvoie -1 en cas d'erreur
  • renvoie -1 sur interruption du signal

Les points importants

  • bof doit pointer vers un emplacement mémoire valide avec une longueur non inférieure à la taille spécifiée en raison d'un débordement.
  • fd doit être un descripteur de fichier valide renvoyé par open() pour effectuer l'opération de lecture car si fd est NULL alors la lecture devrait générer une erreur.
  • cnt est le nombre demandé d'octets lus, tandis que la valeur de retour est le nombre réel d'octets lus. De plus, parfois, l'appel système read doit lire moins d'octets que cnt.

Exemple de read() en 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;> }>

>

>

Sortir

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

Supposons que foobar.txt soit constitué des 6 caractères ASCII foobar. Alors quel est le résultat du programme suivant ?

C


10 millions



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

>

>

Sortir

c = f>

Les descripteurs fd1 et fd2 chacun a sa propre entrée de table de fichiers ouverts, donc chaque descripteur a sa propre position de fichier pour foobar.txt . Ainsi, la lecture de fd2 lit le premier octet de foobar.txt , et la sortie est c = f , pas c = o .

5. C écrire

Écrit les octets cnt de buf dans le fichier ou le socket associé à fd. cnt ne doit pas être supérieur à INT_MAX (défini dans le fichier d'en-tête limites.h). Si cnt vaut zéro, write() renvoie simplement 0 sans tenter aucune autre action.

Le write() est également défini à l'intérieur En tête de fichier.

Syntaxe de write() en C

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

Paramètres

  • fd: descripteur de fichier
  • bouf : tampon à partir duquel écrire les données.
  • raison : longueur du tampon.

Valeur de retour

  • renvoie le nombre d'octets écrits en cas de succès.
  • renvoie 0 en atteignant la fin du fichier.
  • renvoie -1 en cas d'erreur.
  • renvoie -1 sur les interruptions de signal.

Points importants sur l'écriture C

  • Le fichier doit être ouvert pour les opérations d'écriture
  • bof doit être au moins aussi long que spécifié par cnt car si la taille du buf est inférieure à celle du cnt, alors buf entraînera une condition de débordement.
  • cnt est le nombre demandé d'octets à écrire, tandis que la valeur de retour est le nombre réel d'octets écrits. Cela arrive quand fd a moins d'octets à écrire que cnt.
  • Si write() est interrompu par un signal, l'effet est l'un des suivants :
    • Si write() n'a pas encore écrit de données, il renvoie -1 et définit errno sur EINTR.
    • Si write() a réussi à écrire certaines données, il renvoie le nombre d'octets qu'il a écrit avant son interruption.

Exemple de write() en 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);> }>

>

>

Sortir

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

Ici, lorsque vous voyez dans le fichier foo.txt après avoir exécuté le code, vous obtenez un bonjour les geeks . Si le fichier foo.txt contient déjà du contenu, les appels système d'écriture écrasent le contenu et tout le contenu précédent est supprimé et seulement bonjour les geeks le contenu aura dans le fichier.

Exemple : Imprimez hello world à partir du programme sans utiliser de fonction 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;> }>

>

>

Sortir

hello world>

Dans ce code, la chaîne du tableau buf1 Bonjour le monde est d'abord écrit dans stdin fd[0], puis cette chaîne est écrite dans stdin dans le tableau buf2. Après cela, écrivez dans le tableau buf2 sur la sortie standard et imprimez la sortie Bonjour le monde .