Inter-Process Communication (IPC) IPCS 1 1. Code di messaggi 2. Semafori 3. Memoria condivisa send receive 2? 3 p1 p3 p2 CODE DI MESSAGGI
Modello di Comunicazione Code di Messaggi Il processo ricevente può sospendersi in attesa di un messaggio oppure no Send(mesg) MECCANISMO ASINCRONO Receive(mesg) L invio avviene quando il messaggio è pronto; il ricevente si accorge del messaggio solo se va a controllare la coda (non viene avvisato) P1 P2 P3 P4 P5 Più processi possono leggere/scrivere messaggi dalla/nella stessa coda; Mailbox = caso particolare Operazioni relative a una coda di messaggi 1. Creazione coda 2. Invio di un messaggio 3. Recezione di un messaggio 4. Eliminazione coda Una coda è una struttura dati condivisa da più processi: un processo è il creatore, gli altri come possono accedere alla coda??? Se più processi ricevono messaggi in una stessa coda come posso distinguere il destinatario di un particolare messaggio? Chi può inviare messaggi? Chi può leggere messagi da una coda? Quale formato devono avere i messaggi? Code di Messaggi Strutture dati 123 4652 key msqid 0 1 Tabella di Descrittori msqid_ds mode Key: numero che ha senso per il processo ipc_perm msqid: identificatore interno assegnato dal sistema
Che differenza c è fra KEY e MSQID??? Identificatore esterno scelto dall utente 123 4652 key msqid 0 1 Identificatore interno generato e restituito dal sistema È usato dalle system call per inviare e ricevere messaggi Una coda di messaggi è identificata da un numero intero (msqid) al quale è associata una struttura dati (msqid_ds) così costituita: msqid_ds: struct ipc_perm msg_perm; ---prossimo lucido struct msg * msg_first; puntatore al primo messaggio in coda struct msg * msg_last; puntatore all ultimo messaggio in coda ulong_t msg_cbytes; dimensione attuale della coda (in byte) ulong_t msg_qnum; numero dei msg attualmente in coda ulong_t msg_qbytes; max num. di byte ammesso per la coda pid_t msg_lspid; PID dell ultimo processo che ha eseguito una send pid_t msg_lrpid; PID dell ultimo processo che ha eseguito una receive time_t msg_stime; ora di esecuz. dell ultima send time_t msg_rtime; ora di esecuz. dell ultima receive time_t msg_ctime; ora di esecuzione dell ultima msgctl msg_perm: uid_t cuid; UID del creatore della coda gid_t cgid; GID del creatore della coda mode_t mode; diritti di accesso key_t key; chiave 1. Se l effective user id del processo è ROOT l accesso è sempre garantito 2. Se cuid corrisponde all effective user id del processo ed è settato il valore 0600 l accesso è garantito 3. Se il processo ha GID corrispondente a cgid e 0060 è settato l accesso è garantito 4. Negli altri casi se 0006 è settato l accesso è garantito 00400 READ proprietario 00200 WRITE proprietario 00040 READ gruppo 00020 WRITE gruppo 00004 READ altri 00002 WRITE altri
#include <sys/msg.h> int msgget(key_t key, int msgflg); int msgctl(int msqid, int cmd, struct msqid_ds *buf); int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); MSGGET (1) int msgget(key_t key, int msgflg); key_t rinomina del tipo intero Effetti di msgget: 1. Restituisce l identificatore della coda di messaggi associata alla chiave key, se esiste 2. Crea una nuova coda di messaggi se: key = IPC_PRIVATE (costante predefinita) key non ha associata una coda di messaggi e msgflag&ipc_creat vale true 3. - 1 in caso di errore
Esempio di utilizzo di int msgget(key_t key, int msgflg) int msqid; msqid = msgget(1234, IPC_CREAT 666); Numero che ha un senso all interno del mio programma Costante che indica l intenzione di creare una coda se la chiave non ne ha associate OR bit a bit Lettura e scrittura sulla coda abilitate per tutti i processi Esempio di utilizzo di int msgget(key_t key, int msgflg) int msqid; msqid = msgget(1234, 0); Se so che un altro processo deve avere già creato la coda a cui voglio accedere posso passare come msgflg il valore ZERO Inizializzazione della struttura 1. A cuid e a cgid vengono assegnati l effective user id e l effective group id del processo creante 2. Ai 9 bit inferiori di mode.msg_perm vengono assegnati i 9 bit inferiori di msg_flg 3. A qnum, lspid, lrpid, stime ed rtime viene assegnato 0 4. A ctime l ora corrente 5. A qbytes il limite fissato da sistema
Primo modo per far sì che più processi conoscano l id di una stessa coda 1 coda.h #define ID_CODA 789 proc1.c #include coda.h proc2.c #include coda.h Secondo modo per far sì che più processi conoscano l id di una stessa coda 2 padre.c int ID_CODA = msgget(789, IPC_CREAT 666); padre = fork(); if (padre) { <<codice padre>> Padre e figlio possono comunicare attraverso la coda di messaggi } else { << il figlio eredita una copia di ID_CODA >> } Terzo modo per far sì che più processi conoscano l id di una stessa coda 3 proc1.c int ID_CODA = msgget(getppid(), IPC_CREAT 666); Viene usata come chiave un informazione comune (es. due processi con lo sesso padre possono usare il PID del padre proc1.c int ID_CODA = msgget(getppid(), IPC_CREAT 666);
MSGSND MSGSRCV Ci aspettiamo Send(coda, messaggio) Invece abbiamo a disposizione una system call molto più complessa e a basso livello: Send(coda, messaggio, dimensione, azione) int msgsnd(int msqid, id della coda const void *msgp, buffer tipo definito dall utente -- fra due lucidi -- size_t msgsz, è relativo a msgp int msgflg); azione specifica cosa fare se la coda è piena Analogamente ci aspettiamo Receive(coda, &messaggio) Anche in questo caso abbiamo a disposizione una system call molto più complessa e a basso livello Receive(coda, &messaggio, dimensione, tipo, azione) int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); id della coda buffer che conterrà un msg dimensione di msgp tipo di msg da accettare azione da eseguire se non c è un msg del tipo atteso
Non esiste un tipo di dato predefinito per i messaggi, il programmatore può creare una propria struttura a patto che questa contenga i due campi: long mesg_type; Mio_tipo *mesg_data; In una coda possono essere inseriti msg di diverso tipo per destinatari diversi, mesg_type consente di distinguerli È il messaggio vero e proprio: ad es. una stringa di caratteri Es. typedef struct { int mesg_len; long mesg_type; char mesg_data[maxmesgdata]; } mio_messaggio; msgsnd copia i dati spediti nella coda indicata ma NON copia l intera struttura definita dal programmatore! Copia solo mesg_type e gli msgsz byte che seguono mesg_type Es. typedef struct { int mesg_len; Questa parte contiene informazioni di servizio che servono a costruire il messaggio senza farne parte Parte copiata long mesg_type; char mesg_data[maxmesgdata]; } mio_messaggio; msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); mio_messaggio da_spedire; Suppongo che dato venga passato dall utente sprintf(da_spedire.msg_data, val%d, dato); da_spedire.mesg_len = strlen(da_spedire.msg_data); da_spedire.mesg_type = 1; msgsnd(id_coda, (char *)&(da_spedire->mesg_type), da_spedire.mesg_len, 0); Indirizzo di mesg_type 5 1 val32 da_spedire len type data Solo questo pezzo viene spedito! Vengono copiati solo mesg_type e i mesg_len byte successivi a mesg_type
Tramite msgsnd e msgrcv possono essere implementate molte Send e Receive diverse Se non c è spazio aspetta Se non c è spazio termina Bloccante Non bloccante Accetta qualsiasi msg Accetta solo msg di un tipo Le azioni sono codificate in msgflg msgflg può valere (nelle varie system call IPC): 1. IPC_CREAT: se non è associato un oggetto alla chiave, lo crea 2. IPC_EXCL: se non è associato alcun oggetto alla chiave produce un errore 3. IPC_PRIVATE: crea un oggetto privato per il processo 4. IPC_NOWAIT : regola il comportamento in caso di accesso msgsnd: se non c è spazio suff per il messaggio fallisce msgrcv: se non c è un msg del tipo desiderato termina subito MSGCTL
Questa system call consente di eseguire una varietà di operazioni di controllo su di una coda di messaggi: 1. IPC_STAT :: restituisce i valori contenuti nella struttura dati associata a msqid 2. IPC_SET :: assegna valori ai campi della struttura dati associata a msqid 3. IPC_RMID :: disallocazione della coda di messaggi int msgctl(int msqid, id coda su cui eseguire un comando int cmd, comando da eseguire struct msqid_ds *buf); struttura di supporto Restituisce 0 se tutto ok, - 1 in caso di errore