Programmation Système sous Linux/Unix
Dr. Ing. Chiheb Ameur ABID
Contact: [email protected]
Mars 2023
Présentation Chiheb Ameur ABID 2/ 40
Les signaux
Plan
1 Les signaux
Émission d’un signal
Redéfinition du gestionnaire d’un signal
2 Communiquer sur le réseau
Présentation Chiheb Ameur ABID 3/ 40
Les signaux
Les signaux
Préentation
➥ Un signal est un événement asynchrone destiné à un (ou plusieurs) processus.
Z Un signal peut être émis par un processus ou par le système d’exploitation.
➥ Un signal est analogue à une interruption
Z Un processus destinataire réagit à un signal en exécutant un programme de
traitement, ou traitant (handler)
Z La différence est qu’une interruption s’adresse à un processeur alors qu’un signal
s’adresse à un processus
Z Certains signaux traduisent d’ailleurs la réception d’une interruption
➥ Les signaux sont un mécanisme de bas niveau. Ils doivent être manipulés avec précaution
car leur usage recèle des piège
Z Le risque de perte de signaux
Z Ils sont utiles lorsqu’on doit contrôler l’exécution d’un ensemble de processus ou que
l’on traite des événements liés au temps.
Présentation Chiheb Ameur ABID 4/ 40
Les signaux
Les signaux
Fonctionnement
➥ Il existe différents signaux, chacun étant identifié par un nom symbolique : ce nom
représente un entier
➥ Chaque signal est associé à un traitant (handler) par défaut
➥ Un signal peut être ignoré (le traitant est vide)
➥ Le traitant d’un signal peut être changé (sauf pour 2 signaux particuliers)
➥ Un signal peut être bloqué (il n’aura d’effet que lorsqu’il sera débloqué)
➥ Les signaux ne sont pas mémorisés (
Z Risque de perte
Présentation Chiheb Ameur ABID 5/ 40
Les signaux
Les signaux
États d’un signal
➥ Un signal est envoyé à un processus destinataire et reçu par ce processus
Z Tant qu’il n’a pas été pris en compte par le destinataire, le signal est pendant
Z Lorsqu’il est pris en compte (exécution du traitant), le signal est dit traité
➥ Qu’est-ce qui empêche que le signal soit immédiatement traité dès qu’il est reçu ?
Z Le signal peut être bloqué, ou masqué (c’est à dire retardé) par le destinataire. Il est
délivré dès qu’il est débloqué
Z En particulier, un signal est bloqué pendant l’exécution du traitant d’un signal du
même type ; il reste bloqué tant que ce traitant n’est pas terminé
Avertissement !
Il ne peut exister qu’un seul signal pendant d’un type donné (il n’y a qu’un bit par signal pour
indiquer les signaux de ce type qui sont pendants). S’il arrive un autre signal du même type, il
est perdu.
Présentation Chiheb Ameur ABID 6/ 40
Les signaux
Les signaux
Types de signaux
➥ Linux supporte les 32 signaux standard ainsi que les 32 signaux temps réel (normes
POSIX)
➥ Chaque signal est défini par un numéro unique auquel est associé un nom symbolique
(SIG*) ;
Z Éviter d’utiliser les numéros, et préférer les noms explicites (compatibilité entre les
implémentations et sûreté)
Présentation Chiheb Ameur ABID 7/ 40
Les signaux
Les signaux
Les signaux
➥ Récupérer la liste des signaux supportés par le système
kill -l
Présentation Chiheb Ameur ABID 8/ 40
Les signaux
Les signaux
Exemples de signaux
Présentation Chiheb Ameur ABID 9/ 40
Les signaux
Émission d’un signal
Plan
1 Les signaux
Émission d’un signal
Redéfinition du gestionnaire d’un signal
2 Communiquer sur le réseau
Communication en mode connecté
Communication en mode non connecté
Présentation Chiheb Ameur ABID 10/ 40
Les signaux
Émission d’un signal
Les signaux
Émission d’un signal
➥ Émission implicite
Z Division par 0 : engendre SIGFPE (Floating Point Exception)
Z Violation mémoire : engendree SIGSEGV (segmentation fault)
Z Tube sans lecteur reçu lors d’un write() dans un tube par un écrivain sans lecteur :
engendre le signal SIGPIPE
Z Mort d’un fils envoyé par un fils à son père lors de sa terminaison exit : SIGCHLD
Présentation Chiheb Ameur ABID 11/ 40
Les signaux
Émission d’un signal
Les signaux
Émission d’un signal
➥ Émission explicite
Z Seuls les processus issus du même propriétaire peuvent échanger des signaux (mis à
part root).
Z Appel système
1 int kill(pid_t pid,int sig);
Z Commande
1 kill [ -s signal | -p ] [ -a ] pid ...
Présentation Chiheb Ameur ABID 12/ 40
Les signaux
Émission d’un signal
Les signaux
Émission d’un signal
➥ Émettre un signal dans le processus
1 int raise(int sig);
Z Renvoie 0 si OK, sinon -1
Z sig désigne le signal à émettre
Présentation Chiheb Ameur ABID 13/ 40
Les signaux
Émission d’un signal
Les signaux
Émission d’un signal
➥ Planifier l’émission d’un signal SIG_ALARM
1 unsigned int alarm(unsigned int seconds);
Z Renvoie 0 si aucune alarme n’est définie
Z seconds spécifie la durée en secondes après laquelle le signal sera émis
Exemple d’émission d’un signal
1 #include<stdlib.h>
2 #include<unistd.h>
3 #include<signal.h>
4 void raisedAlarm(int sig);
5 int main() {
6 alarm(5);
7 signal(SIGALRM, raisedAlarm);
8 while(1){
9 printf("Hello!\n");
10 sleep(1);
11 }
12 return 0;
13 }
14 void raisedAlarm(int sig) {
15 printf("The Alarm has Raised.\n");
16 }
Présentation Chiheb Ameur ABID 14/ 40
Les signaux
Émission d’un signal
Les signaux
Émission d’un signal
➥ Émettre le signal SIGABRT ce qui entraine la terminaison du processus
1 void abort(void);
Z La terminaison du processus est considérée comme anormale
Z Les fichiers et les pointeurs ouverts ne seront pas fermés
Exemple d’émission d’un signal
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<stdlib.h>
4 #include<signal.h>
5 int main(){
6 int status = fork();
7 if(status == 0){
8 printf("Child Process ID: %d\n", getpid());
9 while(1);
10 }else if(status > 0){
11 printf("Parent Process ID: %d\n", getpid());
12 }
13 abort(); // Child process will continue its execution
14 printf("Due to abnormal termination this line will not execute.\n");
15 return 0;
16 }
Présentation Chiheb Ameur ABID 15/ 40
Les signaux
Émission d’un signal
Les signaux
Mettre en pause un processus
➥ Mettre en pause le processus courant jusqu’à la réception d’un signal
1 int pause(void);
Z Renvoie le signal intercepté si OK, sinon -1
Exemple
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <signal.h>
5 void SIGNAL_HANDLER(int);
6 int main(void){
7 alarm(10);
8 signal(SIGALRM, SIGNAL_HANDLER);
9 if(alarm(7) > 0){
10 printf("An alarm has been set already.\n");
11 }
12 pause();
13 printf("You will not see this text.\n");
14 return 1;
15 }
16 void SIGNAL_HANDLER(int signo){
17 printf("Caught the signal with number: %d\n", signo);
18 exit(0);
Présentation Chiheb Ameur ABID 16/ 40
Les signaux
Émission d’un signal
Les signaux
Mettre en pause un processus
➥ Mettre en pause le processus courant jusqu’à la réception d’un signal ou que la durée est
écoulée
1 unsigned int sleep(unsigned int seconds);
Z Renvoie 0 si la durée est écoulée, sinon le signal intercepté si OK, sinon -1
Présentation Chiheb Ameur ABID 17/ 40
Les signaux
Redéfinition du gestionnaire d’un signal
Plan
1 Les signaux
Émission d’un signal
Redéfinition du gestionnaire d’un signal
2 Communiquer sur le réseau
Communication en mode connecté
Communication en mode non connecté
Présentation Chiheb Ameur ABID 18/ 40
Les signaux
Redéfinition du gestionnaire d’un signal
Les signaux
Redéfinir le traitant d’un signal
➥ Un traitant doit être de type suivant :
1 typedef void (*sighandler_t)(int);
➥ Deux appels systèmes pour définir un traitant :
1 sighandler_t signal(int signum,sighandler_t handler);
2 int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
Z sigaction() est plus complet et plus générique que signal()
Z signal() est plus simple à utiliser
Présentation Chiheb Ameur ABID 19/ 40
Les signaux
Redéfinition du gestionnaire d’un signal
Les signaux
Exemple de redéfinition d’un gestionnaire d’un signal avec signal()
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <unistd.h>
5 void gestionnaire(int numero_signal) {
6 fprintf(stdout,"\n %ld a recu le signal %d \n",(long) getpid(),
7 numero_signal);
8 }
9 int main (void) {
10 int i;
11
12 if (signal(SIGINT, gestionnaire) == SIG_ERR)
13 fprintf(stderr, "Signal %d non capturé \n", SIGINT);
14 while (1)
15 pause();
16 }
Présentation Chiheb Ameur ABID 20/ 40
Communiquer sur le réseau
Plan
1 Les signaux
2 Communiquer sur le réseau
Communication en mode connecté
Communication en mode non connecté
Présentation Chiheb Ameur ABID 21/ 40
Communiquer sur le réseau
Communiquer sur le réseau
Introduction aux sockets
➥ La notion de sockets a été introduite dans les distributions de Berkeley (un fameux
système de type UNIX)
➥ Il s’agit d’un modèle permettant la communication IPC
Z Communiquer sur la même machine
Z Ou en réseau à travers le protocole TCP/IP
➥ On distingue deux modes de communication
❶ Le mode connecté,
❷ Le mode non connecté
Présentation Chiheb Ameur ABID 22/ 40
Communiquer sur le réseau
Communiquer sur le réseau
Schéma général d’une communication en mode connecté
➥ Utilise le protocole TCP.
➥ Une connexion durable est établie entre les deux processus, de telle façon que la socket de
destination n’est pas nécessaire à chaque envoi de données.
Présentation Chiheb Ameur ABID 23/ 40
Communiquer sur le réseau
Communiquer sur le réseau
Principe de la communication IPC avec les sockets
❶ Chaque machine crée une socket,
❷ Chaque socket sera associée (attachée) à un port de sa machine hôte,
❸ Les deux sockets seront explicitement connectées si on utilise un protocole en mode
connecté
❹ Chaque machine lit et/ou écrit dans sa socket,
❺ Les données vont d’une socket à une autre à travers le réseau,
❻ Une fois terminé chaque machine ferme sa socket.
Présentation Chiheb Ameur ABID 24/ 40
Communiquer sur le réseau
Communiquer sur le réseau
Créer une socket
➥ Créer une socket
1 int socket(int domain, int type, int protocol);
Z Retourne un descripteur de fichier si OK, sinon -1 et met le code d’erreur dans
errno
Z domain spécifie le domaine de communication (familles de protocoles)
AF_INET protocole fondé sur IP (IP, TCP, UDP et ICMP)
AF_INET6 protocole IPv6
Z type indique le type de service (orienté connexion ou non).
SOCK_STREAM correspond à une communication en mode connectée, orientée flux
d’octets
SOCK_DGRAM correspond à une communication en mode datagramme, non
connectée
Il existe aussi d’autres types.
Z protocol définit le protocole de communication utilisé par la socket. Souvent, on
le met à 0
Présentation Chiheb Ameur ABID 25/ 40
Communiquer sur le réseau
Communiquer sur le réseau
Attacher une socket
➥ Une socket doit être attachée à une adresse et un port
1 int bind(int fd, struct sockaddr *addr, int addrlen);
Z fd est le descripteur du fichier identifiant le socket
Z addr est une structure qui spécifie l’adresse locale à travers laquelle le programme
doit communiquer. Le format de l’adresse est fortement dépendant du protocole
utilisé
Z addrlen indique la taille du champ addr. On utilise généralement
sizeof(addr).
Présentation Chiheb Ameur ABID 26/ 40
Communiquer sur le réseau
Communiquer sur le réseau
Attente d’une connexion
➥ Mettre le serveur en attente d’une connexion
1 int listen(int socket,int backlog)
Z Renvoie 0 si OK, sinon SOCKET_ERROR
Z socket représente la socket ouverte
Z backlog représente le nombre maximal de connexions pouvant être mises en
attente
Présentation Chiheb Ameur ABID 27/ 40
Communiquer sur le réseau
Communiquer sur le réseau
Établir une connexion sur le serveur
➥ Se connecter à un serveur
1 int connect(int socket,struct sockaddr * addr,socklen_t addrlen)
Z Renvoie 0 si OK, sinon -1
Z socket représente la socket ouverte
Z addr est une structure qui spécifie l’adresse du serveur
Z addrlen indique la taille du champ localaddr. On utilise généralement
sizeof(localaddr).
Présentation Chiheb Ameur ABID 28/ 40
Communiquer sur le réseau
Communiquer sur le réseau
Envoie/Réception
➥ Lire des données (réception)
1 int read(int socket,char * buffer,int len);
➥ Écrire des données (envoie)
1 int write(int socket,char * buffer,int len);
Z Renvoie le nombre d’octets lus (effectivement envoyés) si OK, sinon -1 (code
d’erreur)
Z socket représente la socket ouverte
Z buffer est le tampon de données
Z len est la taille de données à lire (envoyer)
Présentation Chiheb Ameur ABID 29/ 40
Communiquer sur le réseau
Communication en mode connecté
Plan
1 Les signaux
Émission d’un signal
Redéfinition du gestionnaire d’un signal
2 Communiquer sur le réseau
Communication en mode connecté
Communication en mode non connecté
Présentation Chiheb Ameur ABID 30/ 40
Communiquer sur le réseau
Communication en mode connecté
Protocole TCP
Schéma général d’une communication en mode non connecté
➥ Le protocole TCP sert à établir une communication fiable entre deux hôtes
Z Connexion : l’émetteur et le récepteur se mettent d’accord pour établir un connexion.
La connexion reste ouverte jusqu’à ce qu’on la referme.
Z Fiabilité : Suite au transfert de données, des tests sont faits pour vérifier qu’il n’y a
pas eu d’erreur dans la transmission. Ces tests utilisent la redondance des données,
c’est à dire qu’un partie des données est envoyée plusieurs fois. De plus, les données
arrivent dans l’ordre où elles ont été émises.
Z Possiblilité de communiquer sous forme de flot de données, comme dans un tube (par
exemple avec les fonctions read et write). Les paquets arrivent à destination dans
l’ordre où ils ont été envoyés.
➥ Pour une socket destinée à être utilisée avec un protocole TCP/IP (avec connexion TCP)
fondé sur IP (AF_INET), on utilise
1 #include <arpa/inet.h>
2 int sock = socket(AF_INET, SOCK_STREAM, 0);
Présentation Chiheb Ameur ABID 31/ 40
Communiquer sur le réseau
Communication en mode connecté
Communiquer sur le réseau
Exemple de client socket en mode connecté
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <arpa/inet.h>
5
6 int main() {
7 int sock = socket(AF_INET , SOCK_STREAM ,0);
8 struct sockaddr_in addr;
9 addr.sin_family = AF_INET;
10 addr.sin_port = htons(12345); // Port du serveur
11 addr.sin_addr.s_addr = inet_addr("192.168.1.29"); // Adresse IP du serveur (localhost)
12
13 int res = connect(sock, (struct sockaddr*)&addr, sizeof(addr));
14 if(res==-1) { perror("connect"); exit(1); }
15 write(sock, "Hello", 6);
16 char buf[6];
17 read(sock, buf, 6);
18 printf("reçu: %s\n", buf);
19 close(sock);
20 return EXIT_SUCCESS;
21 }
Présentation Chiheb Ameur ABID 32/ 40
Communiquer sur le réseau
Communication en mode connecté
Communiquer sur le réseau
Exemple de serveur socket en mode connecté
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <arpa/inet.h>
6
7 int main() {
8 int sock = socket(AF_INET , SOCK_STREAM , 0);
9 struct sockaddr_in addr;
10 addr.sin_family = AF_INET;
11 addr.sin_port = htons(12345); // Port sur lequel le serveur écoute
12 addr.sin_addr.s_addr = INADDR_ANY; // Écoute sur toutes les interfaces disponibles
13
14 int res = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
15 if (res == -1) { perror("bind"); exit(1); }
16 listen(sock, SOMAXCONN);
17 int cli = accept(sock, NULL, NULL);
18 write(cli, "World", 6);
19 char buf[6];
20 read(cli, buf, 6);
21 printf("reçu: %s\n", buf);
22 close(cli);
23 close(sock);
24 unlink("sock");
25 return EXIT_SUCCESS;
26 }
Présentation Chiheb Ameur ABID 33/ 40
Communiquer sur le réseau
Communication en mode non connecté
Plan
1 Les signaux
Émission d’un signal
Redéfinition du gestionnaire d’un signal
2 Communiquer sur le réseau
Communication en mode connecté
Communication en mode non connecté
Présentation Chiheb Ameur ABID 34/ 40
Communiquer sur le réseau
Communication en mode non connecté
Communiquer sur le réseau
Schéma général d’une communication en mode non connecté
➥ Pas besoin d’établir une connexion
Z La socket est utilisée directement
➥ Les messages sont transmis par partis et de manière désordonnée
Présentation Chiheb Ameur ABID 35/ 40
Communiquer sur le réseau
Communication en mode non connecté
Protocole UDP
Schéma général d’une communication en mode non connecté
➥ Le protocole UDP permet seulement de transmettre les paquets sans assurer la fiabilité
Z Pas de connexion préalable ;
Z Pas de controle d’intégrité des données. Les données ne sont envoyées qu’un fois ;
Z Les paquets arrivent à destination dans le désordre.
Présentation Chiheb Ameur ABID 36/ 40
Communiquer sur le réseau
Communication en mode non connecté
Communiquer sur le réseau
Réception des données en mode non connecté
➥ Lire des données (réception) en mode non connecté
1 ssize_t recvfrom(int socket,char *buf,int len,int flags,sockaddr *from,socklen_t *frlen);
Z Renvoie le nombre d’octets lus (effectivement envoyés) si OK, sinon -1 et code
d’erreur affecté dans errno
Z socket représente la socket ouverte
Z buf est le tampon de données
Z len est la taille de données à lire
Z from pointeur sur la structure contenant l’adresse de la destination définie par
recvfrom
Z frlen est la taille de la structure adresse de la source
Présentation Chiheb Ameur ABID 37/ 40
Communiquer sur le réseau
Communication en mode non connecté
Communiquer sur le réseau
Exemple de réception des données en mode non connecté
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <arpa/inet.h>
5
6 int main() {
7 int sock = socket(AF_INET , SOCK_DGRAM , 0);
8 struct sockaddr_in addr;
9 addr.sin_family = AF_INET;
10 addr.sin_port = htons(12345); // Port sur lequel le serveur écoute
11 addr.sin_addr.s_addr = INADDR_ANY; // Écoute sur toutes les interfaces
12 int res = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
13 if (res == -1) { perror("bind"); exit(1); }
14 printf("Serveur en attente de messages...\n");
15 char buffer[1024];
16 struct sockaddr_in clientAddr;
17 socklen_t clientAddrLen = sizeof(clientAddr);
18 int bytesRead = recvfrom(sock, buffer, sizeof(buffer), 0,
19 (struct sockaddr*)&clientAddr, &clientAddrLen);
20 if (bytesRead == -1) { perror("recvfrom");close(sock);exit(EXIT_FAILURE);}
21 buffer[bytesRead] = ’\0’;
22 printf("Message reçu du client : %s\n", buffer);
23 close(sock);
24 return EXIT_SUCCESS;
25 }
Présentation Chiheb Ameur ABID 38/ 40
Communiquer sur le réseau
Communication en mode non connecté
Communiquer sur le réseau
Envoie des données en mode non connecté
➥ Envoyer des données (réception) en mode non connecté
1 ssize_t sendto(int socket, const void *buf, size_t len,int flags,
2 const struct sockaddr *to,socklen_t tolen);
Z Renvoie le nombre d’octets lus (effectivement envoyés) si OK, sinon -1 et le code
d’erreur est affecté dans errno
Z socket représente la socket ouverte
Z buf est le tampon de données
Z len est la taille de données à envoyer
Z flags spécifie le type de transmission du message> Souvent, on utilise la valeur 0.
MSG_DONTROUTE sert à déboguer les communications sur un réseau en négligeant
les procédures de routage
MSG_PEEK pour lire des données sur une socket TCP sans les extraire de la file
d’attente
Z to pointeur sur la structure contenant l’adresse de la destination
Z tolen est la taille de la structure contenant l’adresse de la destination
Présentation Chiheb Ameur ABID 39/ 40
Communiquer sur le réseau
Communication en mode non connecté
Communiquer sur le réseau
Exemple d’envoie des données en mode non connecté
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <arpa/inet.h>
6
7 int main() {
8 int sock = socket(AF_INET , SOCK_DGRAM ,0);
9 struct sockaddr_in addr;
10 addr.sin_family = AF_INET;
11 addr.sin_port = htons(12345); // Port du serveur
12 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Adresse IP du serveur (localhost)
13
14 const char *message = "hello";
15 if (sendto(sock, message, strlen(message), 0,
16 (struct sockaddr*)&addr, sizeof(addr)) == -1) {
17 perror("Erreur lors de l’envoi du message");
18 close(sock);
19 exit(EXIT_FAILURE);
20 }
21 }
Présentation Chiheb Ameur ABID 40/ 40
Communiquer sur le réseau
Communication en mode non connecté
M ERCI POUR VOTRE ATTENTION
Questions ?