Le carnet On est
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.

2 colonnes denses Format examen Tous prototypes

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 -lpthread dè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