Compagnon · synthèse 2 pages
Feuille recto-verso
Tous les prototypes C utiles le jour J : fork/exec/wait, sigaction, sémaphores, tubes, threads pthread, sockets TCP/UDP, files de messages. Avec en-têtes et patterns canoniques.
1. Processus — fork / exec / wait
Création et terminaison
#include <unistd.h>
#include <sys/wait.h>
pid_t fork(void);
int execl(const char* path, const char* arg, ...);
int execlp(const char* file, const char* arg, ...);
int execv(const char* path, char* const argv[]);
void exit(int status);
pid_t wait(int* status);
pid_t waitpid(pid_t pid, int* status, int opts);
pid_t getpid(void);
pid_t getppid(void);
Macros sur status
WIFEXITED(s) // vrai si sortie normale
WEXITSTATUS(s) // code de retour (0-255)
WIFSIGNALED(s) // vrai si tué par signal
WTERMSIG(s) // numéro du signal qui a tué
Pattern fork classique
pid_t pid = fork();
if (pid == -1) { perror("fork"); exit(1); }
if (pid == 0) {
// fils
execlp("ls", "ls", NULL);
perror("exec"); exit(1);
}
// père
int status;
waitpid(pid, &status, 0);
2. Signaux
Prototypes
#include <signal.h>
int kill(pid_t pid, int sig);
int raise(int sig);
unsigned int alarm(unsigned int sec);
int pause(void);
int sigaction(int sig,
const struct sigaction* act,
struct sigaction* old);
struct sigaction {
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
};
Signaux utiles
- SIGINT (2) — Ctrl+C, fin polie
- SIGQUIT (3) — Ctrl+\, core dump
- SIGKILL (9) — ininterceptable
- SIGSEGV (11) — accès mémoire invalide
- SIGPIPE (13) — write sans lecteur
- SIGTERM (15) — demande poli de fin
- SIGCHLD (17) — fils terminé
- SIGUSR1, SIGUSR2 — libres
Pattern sigaction
void handler(int sig) { ... }
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGINT, &sa, NULL);
3. Sémaphores POSIX
Prototypes
#include <semaphore.h>
int sem_init(sem_t* sem, int pshared, unsigned int value);
int sem_wait(sem_t* sem); // P
int sem_post(sem_t* sem); // V
int sem_trywait(sem_t* sem); // non bloquant
int sem_destroy(sem_t* sem);
Compilation : -lpthread.
Patterns usuels
// Mutex binaire
sem_init(&mutex, 0, 1);
sem_wait(&mutex);
// section critique
sem_post(&mutex);
// Pool de ressources (n places)
sem_init(&pool, 0, n);
// Rendez-vous (signal)
sem_init(&sync, 0, 0);
// Producteur : sem_post(&sync);
// Consommateur : sem_wait(&sync);
4. Tubes (pipes)
Anonymes
#include <unistd.h>
int pipe(int p[2]); // p[0]=R, p[1]=W
ssize_t read(int fd, void* buf, size_t n);
ssize_t write(int fd, const void* buf, size_t n);
int close(int fd);
int dup(int fd);
int dup2(int oldfd, int newfd);
Nommés (FIFO)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int mkfifo(const char* nom, mode_t mode);
int open(const char* path, int flags);
int unlink(const char* path);
// Flags : O_RDONLY, O_WRONLY,
// O_CREAT, O_TRUNC, O_APPEND,
// O_NONBLOCK
Pattern pipeline shell cmd1 | cmd2
int p[2]; pipe(p);
if (fork() == 0) {
dup2(p[1], 1); close(p[0]); close(p[1]);
execlp("cmd1", "cmd1", NULL);
}
if (fork() == 0) {
dup2(p[0], 0); close(p[0]); close(p[1]);
execlp("cmd2", "cmd2", NULL);
}
close(p[0]); close(p[1]);
wait(NULL); wait(NULL);
5. Threads POSIX
Prototypes
#include <pthread.h>
int pthread_create(pthread_t* tid,
const pthread_attr_t* attr,
void* (*func)(void*),
void* arg);
int pthread_join(pthread_t tid, void** ret);
int pthread_detach(pthread_t tid);
void pthread_exit(void* ret);
pthread_t pthread_self(void);
Mutex pthread
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
// ou
pthread_mutex_init(&m, NULL);
pthread_mutex_lock(&m);
// section critique
pthread_mutex_unlock(&m);
pthread_mutex_destroy(&m);
Compilation : gcc fichier.c -lpthread -o prog
6. Sockets TCP / UDP
Prototypes communs
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int socket(int dom, int type, int proto);
int bind(int s, const struct sockaddr* a, socklen_t l);
int listen(int s, int backlog);
int accept(int s, struct sockaddr* a, socklen_t* l);
int connect(int s, const struct sockaddr* a, socklen_t l);
// TCP
ssize_t send(int s, const void* buf, size_t n, int f);
ssize_t recv(int s, void* buf, size_t n, int f);
// ou read/write
// UDP
ssize_t sendto(int s, const void* buf, size_t n, int f,
const struct sockaddr* to, socklen_t tl);
ssize_t recvfrom(int s, void* buf, size_t n, int f,
struct sockaddr* from, socklen_t* fl);
Structures et conversions
struct sockaddr_in {
sa_family_t sin_family; // AF_INET
in_port_t sin_port; // htons(port)
struct in_addr sin_addr; // IPv4
};
int inet_aton(const char* texte, struct in_addr* bin);
char* inet_ntoa(struct in_addr bin);
uint16_t htons(uint16_t x); // host → network
uint16_t ntohs(uint16_t x); // network → host
uint32_t htonl(uint32_t x);
uint32_t ntohl(uint32_t x);
// Constantes utiles
AF_INET // IPv4
SOCK_STREAM // TCP
SOCK_DGRAM // UDP
INADDR_ANY // 0.0.0.0 - toutes interfaces
Pattern serveur TCP (mono-client)
int s = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in srv = {0};
srv.sin_family = AF_INET;
srv.sin_port = htons(8080);
srv.sin_addr.s_addr = INADDR_ANY;
bind(s, (struct sockaddr*)&srv, sizeof(srv));
listen(s, 5);
struct sockaddr_in cli; socklen_t l = sizeof(cli);
int d = accept(s, (struct sockaddr*)&cli, &l);
read(d, buf, sizeof(buf));
write(d, buf, ...);
close(d);
close(s);
7. Files de messages (IPC System V)
Prototypes
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
int msgsnd(int mq, const void* msg,
size_t sz, int flg);
ssize_t msgrcv(int mq, void* msg,
size_t sz, long mtype, int flg);
int msgctl(int mq, int cmd, struct msqid_ds* buf);
Outils shell : ipcs -q (lister), ipcrm -q ID (supprimer).
Structure obligatoire
struct msg {
long mtype; // PREMIER champ, > 0
char data[256]; // payload libre
};
Pattern
int mq = msgget(IPC_PRIVATE,
IPC_CREAT | 0666);
struct msg m = {1, "hello"};
msgsnd(mq, &m, sizeof(m.data), 0);
// mtype = 0 : récupère n'importe lequel
// mtype = T : récupère type T exactement
// mtype = -T : récupère type ≤ |T|
msgrcv(mq, &m, sizeof(m.data), 1, 0);
msgctl(mq, IPC_RMID, NULL); // nettoie
8. Mémo récap
- fork = duplique le processus | exec = remplace le code | wait = synchronise
- signal/sigaction = handlers asynchrones | kill = envoyer un signal
- sem_wait/sem_post = P/V des sémaphores POSIX
- pipe = anonyme + héritage | mkfifo = nommé + ouvert par tout processus
- dup2(fd, 0/1) = redirige stdin/stdout vers fd
- pthread_create + pthread_join = équivalents fork/wait pour threads
- pthread_mutex_lock/unlock = section critique
- TCP serveur : socket → bind → listen → accept → read/write
- TCP client : socket → connect → write/read
- UDP : sendto/recvfrom + bind côté serveur
- htons sur les ports, INADDR_ANY pour bind toutes interfaces
- msgget/msgsnd/msgrcv/msgctl + struct avec long mtype en premier
- Toujours compiler avec
-lpthreaddès qu'on touche aux threads ou sémaphores POSIX - Fermer ce qu'on n'utilise pas : pipes, sockets, sinon EOF jamais détecté
- signal(SIGCHLD, SIG_IGN) évite les zombies dans un serveur fork