Plan global. Programmation système II. Socket du domaine UNIX. Plan. Socket UNIX, Terminaux, Async IO, Mémoire, ELF.



Documents pareils
Programmation système en C/C++

Processus! programme. DIMA, Systèmes Centralisés (Ph. Mauran) " Processus = suite d'actions = suite d'états obtenus = trace

1. Fonctionnement de l Internet 2. Protocoles applicatifs 3. Programmation réseau

Exécutif temps réel Pierre-Yves Duval (cppm)

Cours 6 : Tubes anonymes et nommés

Plan global Outils de développement et compilation. Plan. Objectifs des outils présentés. IDE, GCC/Clang, ASAN, perf, valgrind, GDB.

Programmation système I Les entrées/sorties

Introduction à la Programmation Parallèle: MPI

Playing with ptrace() for fun and profit

Programmation système de commandes en C

Introduction aux Systèmes et aux Réseaux

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Analyse de sécurité de logiciels système par typage statique

Cours de Système : Gestion de Fichiers

IV- Comment fonctionne un ordinateur?

Initiation à la sécurité

Chapitre V : La gestion de la mémoire. Hiérarchie de mémoires Objectifs Méthodes d'allocation Simulation de mémoire virtuelle Le mapping

3IS - Système d'exploitation linux - Programmation système

Architecture des ordinateurs

Dans le chapitre 1, nous associions aux fichiers ouverts des descripteurs de fichiers par lesquels nous accédions aux fichiers.

Cours Programmation Système

THEME 1 : L ORDINATEUR ET SON ENVIRONNEMENT. Objectifs

Communication sous UNIX les sockets

Programmation impérative

Le langage C. Séance n 4

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

GESTION DES FICHIERS C/UNIX

6 - Le système de gestion de fichiers F. Boyer, UJF-Laboratoire Lig, Fabienne.Boyer@imag.fr

SGM. Master S.T.S. mention informatique, première année. Isabelle Puaut. Septembre Université de Rennes I - IRISA

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

Programmation C. Apprendre à développer des programmes simples dans le langage C

Rappels d architecture

Cours de Systèmes d Exploitation

Conventions d écriture et outils de mise au point

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Structure d un programme

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

DUT Informatique Module Système S4 C Département Informatique 2009 / Travaux Pratiques n o 5 : Sockets Stream

Partie 7 : Gestion de la mémoire

Manuel de System Monitor

Network musical jammin

Le système de gestion des fichiers, les entrées/sorties.

Systèmes d exploitation

Développement d un logiciel de messagerie instantanée avec Dotnet (version simplifiée)

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Compilation (INF 564)

Introduction au langage C

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Assembleur. Faculté I&C, André Maurer, Claude Petitpierre

Croisière au cœur d un OS Étape 4 : Mise en place de la pagination

Concept de machine virtuelle

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C


Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

LA mémoire principale est le lieu où se trouvent les programmes et les

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

10 tâches d administration simplifiées grâce à Windows Server 2008 R2. 1. Migration des systèmes virtuels sans interruption de service

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

M2-Images. Rendu Temps Réel - OpenGL 4 et compute shaders. J.C. Iehl. December 18, 2013

Traduction des Langages : Le Compilateur Micro Java

Tutoriel: Création d'un Web service en C++ avec WebContentC++Framework

Plan du cours. Historique du langage Nouveautés de Java 7

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

SYSTÈME DE GESTION DE FICHIERS

REALISATION d'un. ORDONNANCEUR à ECHEANCES

Session 8: Android File System

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Argument-fetching dataflow machine de G.R. Gao et J.B. Dennis (McGill, 1988) = machine dataflow sans flux de données

UE Programmation Impérative Licence 2ème Année

Programmation Réseau. Anthony Busson IUT Info Lyon 1

<Insert Picture Here> Solaris pour la base de donnés Oracle

Système de Gestion de Fichiers

Les structures de données. Rajae El Ouazzani

Cours d initiation à la programmation en C++ Johann Cuenin

Gestion de mémoire secondaire F. Boyer, Laboratoire Sardes

LEs processus coopèrent souvent pour traiter un même problème. Ces

UE C avancé cours 1: introduction et révisions

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

1. Systèmes d entrée/sortie 2. Systèmes de fichiers 3. Structure de mémoire de masse (disques)

La mémoire. Un ordinateur. L'octet. Le bit

Base de l'informatique. Généralité et Architecture Le système d'exploitation Les logiciels Le réseau et l'extérieur (WEB)

KoinKoin. Système d exploitation à architecture basée micro-noyau. Antoine Castaing Nicolas Clermont Damien Laniel

Systèmes d Exploitation - ENSIN6U3. Aix-Marseille Université

Bases de programmation. Cours 5. Structurer les données

IFT Systèmes d exploitation - TP n 1-20%

Virtualisation logicielle De la machine réelle à la machine virtuelle abstraite

Communication par sockets

Réalisation d un OS 32 bits pour PC(x86)

Temps Réel. Jérôme Pouiller Septembre 2011

Applications client/serveur TCP/IP - Sockets Rappels. C.Crochepeyre Applications CS 1

ARDUINO DOSSIER RESSOURCE POUR LA CLASSE

CH.3 SYSTÈMES D'EXPLOITATION

Cours 1 : La compilation

NanoSense. Protocole Modbus de la sonde Particules P4000. (Version 01F)

Java Licence Professionnelle CISII,

Communication inter-processus (IPC) : tubes & sockets. exemples en C et en Java. F. Butelle

SYSTÈME DE GESTION DE FICHIERS SGF - DISQUE

Monter automatiquement des disques distants ou locaux avec automount/autofs

Transcription:

Programmation système II Socket UNIX, Terminaux, Async IO, Mémoire, ELF Timothée Ravier LIFO, INSA-CVL, LIPN 1 re année cycle ingénieur STI 2013 2014 Plan global 1 Socket UNIX 2 Terminaux 3 Autres modèles d entrées / sorties 4 Mémoire 5 Binaire ELF 6 Conseils divers 1 / 57 Plan Socket du domaine UNIX 1 Socket UNIX 2 Terminaux 3 Autres modèles d entrées / sorties 4 Mémoire 5 Binaire ELF 6 Conseils divers Communication inter processus sur un même système ; Exemple : /dev/log/, socket UNIX utilisée pour envoyer des logs au démon syslog (et maintenant journald avec systemd) ; Fonctionnement similaire aux sockets de type AF_INET, sauf pour l adressage : struct sockaddr_un { sa_family_t sun_family; /* Toujours AF_UNIX */ char sun_path[108]; /* Chemain vers la socket: */ }; /* char[] terminé par \0 */ 2 / 57 3 / 57

Socket UNIX : binding const char *SOCKNAME = "/tmp/mysock"; int sfd, ret; struct sockaddr_un addr; sfd = socket(af_unix, SOCK_STREAM, 0); if (sfd == -1) exit_with_error("socket"); memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SOCKNAME, sizeof(addr.sun_path)-1); /* Attention au code de retour de strncpy! */ ret = bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)); if (ret == -1) exit_with_error("bind"); 4 / 57 Échanges sur une socket UNIX Transport fiable : les messages sont livrés dans l ordre et sans duplication ; Taille de paquet potentiellement importante : supérieur à 200ko par défault sous Linux ; ss -x pour lister ces sockets sur un système (anciennement netstat -x). 5 / 57 Messages particuliers Socket UNIX abstraites On peu envoyer des éléments supplémentaires sur une socket UNIX en utilisant sendmsg et recvmsg : SCM_RIGHTS : envoie ou réception d un descripteur de fichiers. Se comporte comme si on avait effectué un dup. SCM_CREDENTIALS : envoie le PID, UID, GID du processus. Potentiellement utilisé pour l authentification. Cf man unix(7). Spécifique à Linux ; Pas de nom dans le système de fichier donc pas de collisions ; Pas besoin de créer un chemin dans le système de fichier ; Socket détruite lorsque qu elle n est plus nécessaire (unlink pour les sockets UNIX classiques) ; Assez peu utilisé. 6 / 57 7 / 57

Plan Terminaux 1 Socket UNIX 2 Terminaux 3 Autres modèles d entrées / sorties 4 Mémoire 5 Binaire ELF 6 Conseils divers Interface de communication avec un programme. Historique en [1] ; Auparavant liés à des éléments matériels, ils sont maintenant la plupart du temps virtuels ; Chaque "console" a son propre terminal : tty ; Plusieurs processus peuvent être rattaché à un terminal mais un seul reçoit les entrées clavier, le processus en avant plan. Les opérations d entrée sortie sont bufferisées lorsque l on utilise bibliothèque C standard : Affichage ligne par ligne pour les terminaux ; Buffer de taille variable sinon (de 4ko à 64ko). 8 / 57 9 / 57 Plan Principe Contexte 1 Socket UNIX 2 Terminaux 3 Autres modèles d entrées / sorties Principe Gestion des évènements signalfd Linux AIO / POSIX AIO Opération synchrones 4 Mémoire 5 Binaire ELF 6 Conseils divers Jusqu à présent, toutes les opérations d entrée / sortie étaient bloquantes ; Ces opérations pouvaient durer un court instant (write() dans un fichier sur le disque) ou très longtemps (read() dans un pipe vide) ; On ne pouvait donc travailler qu avec un seul descripteur de fichier à la fois dans un même processus ou thread ; Chaque connexion crée à partir d une socket devait être gérée dans un thread ou un processus distinct. 10 / 57 11 / 57

Principe Objectifs Principe Attribut O_NONBLOCK Éviter d avoir à créer un thread ou processus par connexion ou fichier lu ; Gérer un ensemble d événements avec un seul thread ; Pouvoir vérifier si une opération est possible sans bloquer l exécution du programme (poll en anglais) ; Optimiser le comportement d un programme effectuant autant d accès disques ou de transferts sur le réseau que possible. Attribut passé à open pour indiquer que l on souhaite effectuer des opérations d entrée sortie non bloquantes ; Attribut associé au descripteur de fichier (affecte tous les threads et les processus fils) ; fcntl(int fd, int commande) : pour changer cette attribut sur un descripteur de fichier déjà ouvert : int ret = fcntl(fd, F_GETFL); if (ret!= -1) fcntl(fd, F_SETFL, ret O_NONBLOCK); Des versions spécifiques Linux de certains appels systèmes (socket) permettent aussi de préciser cette option. 12 / 57 13 / 57 Principe Utilisation Principe Implémentation naïve Toutes les opérations de lecture et écriture ne seront plus bloquantes et peuvent donc échouer pour diverses raisons ; Il faut donc impérativement vérifier le code de retour de tous ces appels systèmes ; On boucle sur les descripteurs de fichiers disponibles et l on effectue nos opérations ; Peu efficace car consomme du temps CPU pour rien. Valeur d errno : EAGAIN et EWOULDBLOCK. 14 / 57 15 / 57

Alternatives Polling vs non bloquant Multiplexage des entrées / sorties : select() et poll() permettent de surveiller un ensemble de descripteurs pour déterminer si une opération est possible. Entrées sorties guidée par signaux : demande au noyau d indiquer à un processus par un signal qu une opération est possible sur un descripteur de fichier. Meilleures performances que select() et poll() pour une grande quantité de descripteurs de fichiers ; Lorsque l on utilise select(), poll() et epoll(), il n est pas nécessaire de rendre les descripteurs de fichiers non bloquants ; En revanche, ces deux modes d opération sont souvent combinés. epoll() : spécifique Linux, pas de signaux, configuration plus fine, performant. 16 / 57 17 / 57 select int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict timeout); Surveille les évènements se produisant sur un ensemble de descripteurs de fichiers ; Possibilité d attendre indéfiniment ou de s arrêter après un certain temps (timeout) ; select int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict timeout); On utilise FD_ZERO, FD_SET, FD_CLR, FD_ISSET pour manipuler les fd_set ; nfds doit être d au moins la valeur du plus grand descripteur de fichier + 1 ; readfds : ensemble de descripteurs de fichiers sur lesquels on surveille l arrivée d input ; writefds : ensemble de descripteurs de fichiers sur lesquels on surveille la possibilité d output ; exceptfds : ensemble de descripteurs de fichiers sur lesquels on surveille si une condition exceptionnelle s est produite. 18 / 57 Lorsque select retourne la main (avec un code de retour positif), les fd_set ne contiennent plus que les fd qui peuvent être manipulés ; Il faut alors tester chaque fd que l on veut suivre pour regarder si il est dans le fd_set ; Exemple en TD. 19 / 57

poll Constat int poll(struct pollfd fds[], nfds_t nfds, int timeout); On remplace les sets de fd par un seul tableau avec sa taille (nfds) ; Chaque élément du tableau est une structure qui indique quels événements on souhaite suivre ; timeout : select et poll sont portables, mais lents et peu pratiques à utiliser dès que l on travaille avec beaucoup de descripteurs de fichiers ; -1 : bloque indéfiniment ; 0 : ne bloque pas, effectue juste la vérification ; n > 0 : bloque pendant n millisecondes. Le code de retour correspond au nombre de fd qui sont prêts. 20 / 57 21 / 57 Gestion avec les signaux epoll Être prévenu par un signal qu une opération est possible ; Mise en place d un gestionnaire de signal (généralement temps réel) ; On associe un processus (ou thread) à un descripteur de fichier : fctnl (fd, F_SETOWN, getpid()); On définit un signal à envoyer : fcntl (fd, F_SETSIG,numerosignal); A éviter (Rappel : écrire un gestionnaire de signal correct est dur). La liste des descripteurs de fichiers à suivre est maintenant stockée dans le noyau ; On s y réfère à l aide d une instance sous forme de descripteur de fichier : int epoll_create(int size); On manipule la liste avec : int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev); On attends un événement avec : int epoll_wait(int epfd, struct epoll_event *evlist, int maxevents, int timeout); 22 / 57 23 / 57

Gestion des évènements libevent, libev... signalfd signalfd Plusieurs bibliothèques en C propose une interface de plus haut niveau pour gérer les entrées sorties sur les descripteurs de fichier ; Abstrait aussi les différences entre les UNIX et Windows ; Elles ajoutent généralement la gestion des «timers» ; Simplifie notablement la gestion des entrées sorties. La gestion des signaux est fastidieuse et écrire un gestionnaire de signal correct est très difficile ; int signalfd(int fd, const sigset_t *mask, int flags); Crée un descripteur de fichier pour recevoir les signaux de façon asynchrone ; Il faut bloquer les signaux (sigprocmask) et les traiter ensuite en lisant les informations depuis le descripteur de fichier de signalfd. 24 / 57 25 / 57 signalfd signalfd : utilisation Linux AIO / POSIX AIO Async IO : Linux AIO / POSIX AIO Rappel : SIGKILL et SIGSTOP ne peuvent pas être gérés ; SIGBUS, SIGFPE, SIGILL, et SIGSEGV sont générés à la suite d une erreur d exécution d une instruction et ne peuvent pas être gérés par signalfd ; Ils doivent être traités sur l instant. Il faut donc : écrire un gestionnaire de signaux minimal pour SIGBUS, SIGFPE, SIGILL, et SIGSEGV ; gérer les autres signaux avec signalfd. Peu utilisé, mais potentiellement très performant (voir [2] et aio(7)) ; Principe : Soumettre des opérations à effectuer, laisser le noyau les traiter de façon asynchrone, vérifier que les opérations ont été correctement effectuées ; On peut être notifié soit à l aide de signaux, par l exécution d un thread, ou rien du tout. Exemple complet en TD. 26 / 57 27 / 57

Linux AIO / POSIX AIO Async IO : Linux AIO / POSIX AIO Opération synchrones Attribut O_DIRECT, O_DSYNC, O_SYNC 1 Ouverture d un contexte pour soumettre et valider la complétion d une requête d entrée / sortie ; 2 Création d une ou plusieurs requêtes et configuration pour indiquer quelles opérations doivent être effectuées ; 3 Soumission de ces requêtes au contexte d entrée / sortie, qui va les envoyer au noyau pour qu elles soient effectuées ; 4 Vérifier la complétion des requêtes d un contexte ; 5 Retour en 2 si nécessaire. 28 / 57 Attributs passés à open ou appliqués sur un descripteur de fichier avec fcntl() ; O_DIRECT : indique au noyau qu il doit minimiser les effets de cache liés à un fichier. Dans la plupart des cas, cela réduit les performances. Aucune garantie n est donnée lors de l écriture de données sur le disque (les données ne sont pas toujours écrites directement comme l option pourrait laisser l entendre) ; O_DSYNC et O_SYNC : assure que les données sont écrites sur le disque lorsque l appel système write se termine. Différence mineure entre O_DSYNC et O_SYNC (cf open(2)). Privilégier O_DSYNC. 29 / 57 Plan Mémoire physique 1 Socket UNIX 2 Terminaux 3 Autres modèles d entrées / sorties 4 Mémoire 5 Binaire ELF 6 Conseils divers La mémoire physique est composée de mots contigus repérés par une adresse physique ; Ces mots peuvent être de longueur différente : 8, 16, 32, 64, 128 bits ; Généralement, l octet est la plus petite unité adressable par un processeur. 30 / 57 31 / 57

Mémoire cache Gestion du cache Les accès direct à la mémoire principale depuis le processeur sont longs par rapport à la vitesse d exécution des instructions du processeur ; Présence des mémoires caches ; On cherche les informations en premier dans les caches et ensuite dans la mémoire centrale. Principe de la localité pour déterminer si un mot va être mis dans le cache : Localité spatiale : si un mot est demandé, les mots voisins ont une forte chance d être demandés ; Localité temporelle : si un mot est demandé à l instant t, il est probable qu il le soit à nouveau à l instant t+1... 32 / 57 33 / 57 Gestion de la mémoire cache Lorsque le contenu d un mot est modifié dans la mémoire cache une opération est prévue pour qu il soit aussi modifié dans la mémoire centrale : Soit immédiatement : «write-through» ; Soit lorsque l on retire ce mot de la mémoire cache : «write-back». 34 / 57 Espace d adressage d un processus Les processus ne travaillent pas directement avec les adresses mémoires correspondants à l emplacement des données dans la mémoire physique ; On alloue à chaque processus un espace d adressage virtuel ; Celui-ci est de taille variable suivant l architecture : Intel i386 ou x86 : 32 bits = 2ˆ32 (4GiB) ; AMD64 ou x86-64 : 64 bits = 2ˆ64 (16 EiB). Les implémentation matérielles sont encore limitées à 2ˆ48 octets pour l adressage physique (256 TiB). 35 / 57

Espace d adressage virtuel d un processus Gestion de la mémoire Mémoire réservée au noyau Variables d'environnement Arguments Pile (stack) Tas (heap) BSS segment : variables globales et statiques non initialisées Data (ro + rw) : variables globales et statiques non nulles Data segment Code segment 0xFFFFFFFF FFFFFFFF 0x00000000 00000000 L espace d adressage virtuel est découpé en «segments» ou «pages», qui font généralement 4kiB ; Pour accéder à une donnée dans une page, il faut indiquer son décalage ou «offset» ; L espace d adressage physique est aussi découpé en morceaux : les cadres (frames) ; Pour accéder aux données dans la mémoire, il faut faire correspondre une adresse virtuelle utilisée par un programme avec une adresse physique (donc faire correspondre les pages avec les cadres) ; 36 / 57 37 / 57 Memory Management Unit Accès et changement de contexte Pour cela le noyau maintient une table de pages par processus (avec plusieurs niveaux d indirection) ; Il y maintient l association entre cadre et pages ; Cette table est chargée dans la Memory Management Unit (MMU) avant l exécution de chaque processus ; La MMU contient un registre qui référence l ensemble des zones mémoire associées à un processus ; C est un élément matériel pour avoir de meilleures performances. Des bits de protection (RWX) sont associés à chaque page ; Lorsqu un processus veut accéder à une valeur, la MMU s assure que la zone est bien enregistrée pour ce processus, que les restrictions sont respectées et effectue la correspondance pour que le processeur utilise l adresse physique ; À chaque changement de contexte (changement de processus en cours d exécution), il faut changer la table dans la MMU puisque chaque table est propre à un processus. 38 / 57 39 / 57

Conversion des adresses virtuelles Allocation (version simplifiée) Lorsque qu un programme fait appel à malloc, deux cas peuvent se produire : Il n y a pas de pages avec de l espace disponible pour ce processus. malloc demande au noyau de lui allouer plus d espace mémoire et retourne un emplacement valide dans cette nouvelle page ; Il reste de la place dans les pages allouées au processus : malloc retourne une adresse qui pointe vers une zone libre de taille au moins égale à la taille demandée (généralement arrondie à un multiple de 2 supérieur) ; 40 / 57 41 / 57 Pagination et SWAP Plan La quantité de mémoire présentée aux processus est plus importante que la quantité réelle de mémoire disponible ; Lorsqu il n y a plus de place dans la mémoire, les pages les moins utilisées sont déplacées dans la SWAP. L état de chaque page est stocké dans la table des pages ; Si un accès est effectué à une page stockée dans la SWAP, le noyau demande le chargement dans la RAM de cette page ; Si il n y a plus de place dans la RAM, alors il faut au préalable déplacer une autre page ou si la SWAP est pleine, tuer un processus pour faire de la place. 42 / 57 1 Socket UNIX 2 Terminaux 3 Autres modèles d entrées / sorties 4 Mémoire 5 Binaire ELF 6 Conseils divers 43 / 57

Executable and Linking Format (ELF) Format de fichier binaire standard pour stocker les exécutables, les bibliothèques dynamiques, le code objet (fichiers.o) et les core dumps ; Format couramment utilisé sous les systèmes UNIX et Linux ; file : utilitaire permettant de déterminer le type d un fichier ; readelf, objdump : outils pour lire les informations d un fichier ELF. 44 / 57 Executable and Linking Format (ELF) $ readelf -a /usr/bin/ls ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00... Class: ELF64 Data: 2 s complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x40487f Start of program headers: 64 (bytes into file) Start of section headers: 108312 (bytes into file)... 45 / 57 Plan Gestion du signal SIGPIPE I 1 Socket UNIX 2 Terminaux 3 Autres modèles d entrées / sorties 4 Mémoire 5 Binaire ELF 6 Conseils divers 46 / 57 Se produit lorsque l on essaie d écrire dans un pipe ou une socket qui n est plus associé à un processus en lecture ; Exemples : terminaison abrupte ou volontaire du lecteur (close(pipe);), déconnexion abrupte ou volontaire... Comportement par défaut : Terminaison du programme ; Le code de retour de write est alors SIGPIPE ; Il est toujours plus facile de travailler avec le code de retour d une fonction qu avec des signaux ; On ignorera ou bloquera donc toujours SIGPIPE. 47 / 57

Gestion du signal SIGPIPE II Code propre : gestion des erreurs I Deux choix possibles suivant le contexte : Si l on peut changer la gestion des signaux : ignorer le signal et traiter correctement le code de retour de write, send ou sendmsg ; Sinon (si l on écrit une bibliothèque par exemple) : utiliser l option MSG_NOSIGNAL avec send ou sendmsg et ne pas utiliser directement write. Traiter le code de retour proprement ; L option SO_NOSIGPIPE pour les sockets n est pas supportée sous Linux. 48 / 57 Il est impératif de vérifier tous les codes de retour de toutes les fonctions en C ; Il faut traiter tous les cas précautionneusement ; Si l on souhaite se débarrasser de certains cas de façon systématique, on peut écrire : ssize_t Read(int fd, void *buf, size_t count) { ssize_t ret = read(fd, buf, count); if ((ret == -1) && (errno == EIO)) { perror("read"); exit(exit_failure); } else { return ret; } } 49 / 57 Code propre : gestion des erreurs II Il est parfois judicieux d arrêter l exécution du programme rapidement en cas d erreur pour ne pas entraîner de bugs difficiles à comprendre plus tard. 50 / 57 Code propre : read/write ssize_t taille_lue = read(stdin_fileno, buffer, buffer_size); if (taille_lue == -1) { perror("erreur read STDIN"); exit(exit_failure); } else if (taille_lue == 0) { break; } /* EOF */ else { ssize_t taille_ecrite = 0; while (taille_ecrite < taille_lue) { retour_write = write(tube, buffer + taille_ecrite, taille_lue - taille_ecrite); if (retour_write == -1) { perror("erreur write tube"); exit(exit_failure); } taille_ecrite += retour_write; } } 51 / 57

Code propre : utiliser les bons types pour les tailles Evitez : int i; for (i = 0; i < z; i++) { // code } Préférez : size_t i; for (i = 0; i < z; ++i) { // code } Le dépassement de la taille d un entier signé est une opération indéfinie ; Le dépassement de la taille d un entier non signé est une opération complètement définie : la valeur boucle à zéro. 52 / 57 Code propre : limiter la complexitée du code I Il est très facile de faire des erreurs en C : = au lieu de == dans un if ; oubli des { } pour une boucle for avec plusieurs instructions ;... Il faut donc essayer de limiter la complexité du code en réduisant chaque ligne à une expression la plus simple possible ; Il ne faut pas avoir peur d ajouter des variables intermédiaires si cela facilite la lecture ; Le compilateur se chargera d optimiser l usage de la mémoire à ce niveau. 53 / 57 Code propre : limiter la complexitée du code II Evitez : if (read(fd, buff, size) < 0) { // erreur } else { // code } Préférez : ssize_t ret = read(fd, buff, size); if (ret > 0) { // ok } else if (ret == 0) { // EOF ] else { // erreur } 54 / 57 Code propre : limiter la complexitée du code II Evitez : for (i = 0; i < z; z++) { tab[i++][a--][x] = a; *(--b) = a++; } Vous risquez de tomber sur des cas non définis dans le standard C (undefined behavior) ce qui peut mener à des bugs difficiles à trouver ; Préférez la version longue avec les variables intermédiaires ; Le compilateur optimisera sans aucun soucis les codes source de ce type. 55 / 57

Petite pensée pour le créateur du C et d UNIX : Dennis Ritchie Références I 1 The TTY demystified : http://www.linusakesson.net/programming/tty/ ; 2 AIO User Guide : https: //code.google.com/p/kernel/wiki/aiouserguide. 3 Linux Kernel Development (3rd Edition) by Robert Love. 4 ELF 101 posters : https://code.google.com/p/corkami/wiki/elf101 5 Schéma de traduction des adresses virtuelles en adresses physiques : http: //fr.wikipedia.org/wiki/m%c3%a9moire_virtuelle 56 / 57 57 / 57