Fino a qualche anno fa i problemi sulla comunicazione e sincronizzazione tra processi, IPC ( Inter Process Communication ), erano grandi e complessi. L’avvento dei sistemi operativi realmente multitasking per i personal computer ha cambiato le cose. In questo articolo vedremo i tipi di comunicazione tra processi soffermandoci sull’invio dei segnali in ambiente Linux.
Esistono due modi di comunicazione tra processi, basati su due principi diversi ma ugualmente potenti:
Grazie alla lunghissima storia di UNIX che parte dalla fine degli anni ’60 esistono molti sistemi IPC, ogni meccanismo però può essere ricondotto all’invio di messaggi o scambi di porzioni di memoria. Una delle possibilità più grezze e meno versatili è quella dei segnali che consentono l’invio di messaggi ad un processo con un numero identificativo che rappresenta il comando. Esistono poi le pipe, poi vennero i socket ( diversi da quelli INET che servono per comunicazioni di rete, qui servono per la comunicazione tra processi della stessa macchina ), i semafori per la sincronizzazione, la memoria condivisa e le code di messaggi. In questo articolo vedremo i segnali, facendo al termine un piccolo esempio di programmazione.
Un segnale è un evento contraddistinto da un numero che viene recapitato ad un processo che può gestirlo in vari modi:
Il meccanismo dei segnali può essere grossolanamente classificato in uno scambio di messaggi, ma talmente primitivo che non c’è modo di conoscere chi ha inviato il segnale. All’inizio i segnali furono inventati per dare al kernel la possibilità di indicare qualcosa ad un processo. Il segnale ha un numero identificativo che ne indica il comando da effettuare, vediamo i principali:
Questi valori dipendono dal sistema operativo e dall’architettura della macchina, per leggerli occorre aprire il file /usr/include/linux/signal.h che sul mio x86 in Ubuntu 10.04 risiede in /usr/include/asm/signal.h; altro modo di studiare questi valori è dare il comando man 7 signal.
Per mandare un segnale ad un processo si può utilizzare sia un programma eseguibile che una chiamata di sistema, entrambi si chiamano kill, ma la loro sintassi è diversa. La sintassi per il programma eseguibile è:
kill -segnale numProcesso
il primo argomento è il numero del segnale da inviare, basta eliminare SIG dal nome della costante; quindi per inviare un hangup al processo 1500 basta scrivere:
kill -1 1500
o
kill -HUP 1500
per sapere l’identificativo del processo basta dare il comando ps ( vedere l’articolo sulla gestione dei processi in Linux ). Esiste poi la variante killall con la quale si usa il nome del processo da terminare come in questo esempio:
killall -HUP inetd
UNIX autorizza l’invio dei segnali solo ai processi di cui si è proprietari, l’utente root può inviarli a tutti.
I segnali sono gestiti in modo asincrono, cioè si predispone una funzione che viene chiamata quando arriva un certo segnale, ma non si sa a priori quando questa funzione sarà eseguita. Il gestore del segnale è chiamato handler ed è una funzione che riceve un parametro int e non restituisce nulla; il valore dell’argomento è il numero del segnale. Per indicare la funzione handler si utilizza una funzione dichiarata in signal.h che si chiama appunto signal, vediamone il prototipo:
func* signal(int numSegnale, func* gestore)
Al posto di gestore possiamo indicare SIG_IGN che indica che si vuole ignorare il segnale o SIG_DFL che indica che si vuole ripristinare l’azione di default. Vediamo ora un piccolo esempio per mettere in pratica quello che abbiamo appreso in questo articolo:
#include “stdio.h”
#include “signal.h”
#include “unistd.h”
#include “stdlib.h”
void Uscita(int iSegnale)
{
printf(“Va bene esco perché sei gentile!\n”);
exit(0);
}
void Seccato(int iSegnale)
{
printf(“\nEsco, però sei molto sgarbato!\n”);
&n
bsp; exit(0);
}
int main(int argc, char** argv)
{
signal(SIGTERM, Uscita);
signal(SIGINT, Seccato);
printf(“Che bello essere in esecuzione con PID %d\n”, getpid());
scanf(“Per fermare il programma”);
return 0;
}
Per compilare il programma date il seguente comando:
gcc -Wall -o signal signal.c
ovviamente con il nome del vostro file sorgente. Ora eseguite l’applicazione e terminatela con Ctrl+C, vi verrà scritto un messaggio sul terminale per il segnale SIGINT. Eseguite nuovamente l’applicazione ed aprite un’altra finestra console, qui date il comando:
kill -SIGTERM PID
il PID lo ricevete quando eseguite il programma.
In questo articolo abbiamo parlato dei segnali, forse in futuro proporrò anche altri articoli su pipe, socket o memoria condivisa, ma dovrete essere voi che mi dovete dire se vi piacerebbe approfondire l’argomento sulle comunicazioni tra processi in Linux, potete scrivere un commento all’articolo o iscrivendovi al forum.
Sono arrivato alla convinzione che un abbonamento per tutti i miei software gestionali sia il…
MerciGest è un software per la gestione del magazzino completamente gratuito. Continua a leggere→
In ufficio può capitare di doversi allontanare dal proprio posto di lavoro, ecco che allora…
In questo articolo vedremo quando è più o meno utile togliere la corrente ad un…
Dopo la pausa invernale dovuta al lavoro che devo fare per sostentarmi, eccomi di nuovo…
Vediamo come eliminare i files direttamente da Windows senza utilizzare il cestino. Continua a leggere→