• Non ci sono risultati.

INTER-PROCESS

N/A
N/A
Protected

Academic year: 2021

Condividi "INTER-PROCESS "

Copied!
12
0
0

Testo completo

(1)

1

INTER-PROCESS

COMMUNICATION (IPC) SYSTEM

(Bach: “the Design of the

Unix Operating System”; manuale on-line)

- Memoria Condivisa (Shared Memory) - Semafori

- Code di Messaggi

(Sulle sito del corso trovate alcuni programmi C che illustrano l’uso di queste system call)

2

IPC

• Le Inter-Process Communication Utilities (di solito abbreviato in IPC) sono una serie di system call che permettono di allocare ed usare determinate strutture per la comunicazione e la sincronizzazione tra processi in Unix

• Sebbene comunicazione e sincronizzazione possano essere realizzate in Unix anche senza l’uso delle IPC, queste ultime offrono dei meccanismi molto più sofisticati e versatili

(2)

3

Memoria Condivisa

P1

--- ---

P2

--- ---

C I A O read

read

write read

write write

• Quattro syscall sono disponibili per gestire la memoria condivisa (MC): shmget, shmctl, shmat, shmdt

4

Memoria Condivisa

• Normalmente, ogni processo possiede uno spazio di indirizzamento logico separato da tutti gli altri

• Un segmento di MC invece, può essere letto e/o scritto da due o più processi, e permette quindi un rapido scambio di informazioni.

• Quindi, ogni processo usa il segmento di MC come se fosse una normale porzione del proprio spazio di indirizzamento logico, che però è in comune a più processi

• Tipicamente, l’accesso ai dati presenti in un segmento di MC deve essere regolato come una sezione critica

(3)

5

Memoria Condivisa

• Quando più processi devono usare un segmento di MC, uno di questi preleva il segmento (shmget), e rende noto agli altri processi l’identificatore con cui potrà essere usato il segmento.

• un segmento appena prelevato è un’ area di RAM “grezza”.

Per poter essere usato da un processo, deve essere

“attaccato” (shmat) allo spazio di indirizzamento di quel processo, specificando anche il tipo della struttura dati che verrà memorizzata nel segmento (uguale per tutti i processi)

• Quando un processo non vuole più usare un segmento, lo

“stacca” (shmdt) dal suo spazio di indirizzamento, o lo rimuove (shmctl).

6

/* ESEMPIO DI PRELIEVO E USO DELLA MEMORIA

CONDIVISA: shmuse.c */

#include<stdio.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

main() {

int i,n,w;

int shmid;

char buffer[10]; /* l’array che metteremo nella shared memory */

char *pun1, *pun2;

shmid = shmget(IPC_PRIVATE, sizeof(buffer[10])*10, 0666);

if (shmid == -1) {

printf("errore creazione memoria\n");

exit(0);

}

preleva un nuovo segmento di memoria

dimensione del segmento

protezioni sul segmento

(4)

7

else printf("prelevata memoria id = %d\n",shmid);

n = fork(); /* facciamo conto che non possa fallire... */

if ( n == 0) { /* processo figlio */

printf("(figlio) mando un messaggio al padre

su memoria condivisa\n");

pun1 = (char *)shmat(shmid, 0, SHM_RND);

pun1[0] = 'c';

pun1[1] = 'i'; pun1[2] = 'a';

pun1[3] = 'o'; pun1[4] = '\0';

printf("(figlio) ora aspetto 3 secondi\n");

for (i=0; i<3; i++) { system("sleep 1");

printf(".\n");

}

printf("(figlio) ho finito e muoio\n");

exit(10);

}

attacca il segmento dove possibile nello spazio

dati del processo read/write (flag is not

SHM_RDONLY)

8

else /* processo padre */

{

printf("(padre) aspetto il figlio e leggo il suo messaggio\n");

w = wait(0);

pun2 = (char *)shmat(shmid,0,SHM_RND);

printf("(padre) messaggio del figlio: ");

for (i = 0; i < 5; i++)

printf("%c",pun2[i]);

printf("(padre) ora rimuovo la memoria condivisa e muoio anch'io\n");

shmctl(shmid,IPC_RMID,0);

exit(0);

}

} rimuovi il

segmento

(5)

9

output del programma shmuse.c

prelevata memoria id = 100

(figlio) mando un messaggio al padre su mem. cond.

(figlio) ora aspetto 3 secondi

(padre) aspetto il figlio e leggo il suo messaggio .

. .

(figlio) ho finito e muoio

(fpadre) messaggio dal figlio: ciao

(padre) rimuovo la mem. cond. e muoio anch’io

10

Semafori

P1

--- ---

P2

--- ---

semaforo

wait signal

• Tre syscall sono disponibili per gestire i semafori:

semget, semctl, semop

(6)

11

Semafori

• La syscall semget permette di prelevare un array di semafori (da 1 a MAXINT semafori)

• Per gestire i semafori, si deve usare un array di elementi di tipo sembuf (tipo predefinito) che conterranno informazioni relative al corrispondente semaforo

semaforo 0 semaforo 1 semaforo 2 ...

sem_num sem_op sem_flg

posizione della struttura (e del corrispondente semaforo) nell’array valore da sommare alla variabile semaforica

che fare se il semaforo è ≤ 0 sembuf:

12

/* ESEMPIO DI PRELIEVO E USO DI UN SET DI SEMAFORI:

semuse.c */

#include<stdio.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

main() {

int i,n,w,semval,semid;

struct sembuf sops[1];

semid = semget(IPC_PRIVATE,1,0666);

if (semid == -1){

printf("errore creazione set di semafori\n");

exit(0);

} else

printf("\nprelevato set di semafori id = %d\n",semid);

array di strutture sembuf per gestire i semafori prelevati

preleva un nuovo set di semafori quanti semafori nel set

read/write per tutti

(7)

13

i = semctl(semid,0,GETVAL,0);

printf("\nvalore iniziale del primo semaforo = %d\n",i);

n = fork();

if (n == -1){

fprintf(stderr,"fork fallita\n");

exit(1);

}

else if ( n == 0) /* processo figlio */{

sops[0].sem_num = 0; /* operazione sul semaforo 0 */

sops[0].sem_op = -1; /* decrementa il semaforo di 1: WAIT */

sops[0].sem_flg = 0; /* che fare: wait se semaforo = 0 */

printf("\n(figlio) tento di decrementare il semaforo, mi sospendo se vale 0\n");

i = semop(semid,sops,1);

printf("\n(figlio) ho decrementato il semaforo e muoio\n");

exit(0);

}

notate la ridondanza...

lunghezza dell’array sops

14

else /* processo padre */

{

printf("\n(padre) ora aspetto 2 secondi\n");

for (i=0; i<2; i++) {

system("sleep 1");

printf("*\n");

}

printf("\n(padre)ora sveglio il figlio incrementando il

semaforo\n");

sops[0].sem_num = 0; /* operazione sul semaforo 0 */

sops[0].sem_op = 1; /* tipo di operazione: incrementa il semaforo: SIGNAL */

sops[0].sem_flg = 0; /* che fare: ininfluente */

i = semop(semid,sops,1);

(8)

15

printf("\n(padre) ora aspetto altri 2 secondi\n");

for (i=0; i<2; i++) {

system("sleep 1");

printf("*\n");

}

printf("\n(padre) ora rimuovo il semaforo e muoio anch'io\n");

semctl(semid,IPC_RMID,0);

exit(0);

} }

16

output del programma semuse.c

prelevata set di semafori id = 100 valore del semaforo = 0

(figlio) tento di decrementare il sem., mi sospendo se vale 0 (padre) ora aspetto 2 secondi

*

*

(padre) ora sveglio il figlio incrementando il semaforo (figlio) ho decrementato il semaforo e muoio

(padre) ora aspetto due secondi

*

*

(padre) ora rimuovo il semaforo e muoio anch’io

(9)

17

Code di Messaggi

P1 --- ---

m1 m2 m2 ...

send

send receive

• Quattro syscall sono disponibili per gestire le code di messaggi: msgget, msgsnd, msgrcv, msgctl

P3 --- ---

P2 --- ---

P4 --- ---

receive

receive

send

18

Code di Messaggi

• Quando più processi devono usare una coda di messaggi, uno di questi preleva la coda (msgget), e rende noto agli altri processi l’identificatore della coda

• più processi possono inviare (msgsnd) e ricevere (msgrcv) messaggi sulla stessa coda. Un messaggio ricevuto da un processo viene “consumato”.

• Ogni messaggio ha un tipo (indicato da un numero usato nella msgsnd). Un processo in ascolto su una coda può decidere di ricevere qualsiasi messaggio, o solo quelli di un determinato tipo. Se nessun messaggio di quel tipo è

presente nella coda, il processo può decidere di sospendersi.

(10)

19

/* USO DI UNA CODA DI MESSAGGI: msguse.c */

#include<stdio.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

main( ){

int i,n,w;

int msgid;

struct msgbuf1 { /* struttura che contiene: */

long mtype; /* tipo del messaggio; */

char mtext[100] /* il messaggio; */

} sndbuf, rcvbuf, *msgp;

msgid = msgget(IPC_PRIVATE,0666);

if (msgid == -1) {

printf("errore creazione coda di messaggi\n");

exit(0);

} else printf("\nprelevata coda di messaggi id = %d\n",msgid);

20

n = fork();

if (n == -1){

fprintf(stderr,"fork fallita\n");

exit(1);

}

else if ( n == 0){ /* processo figlio */

printf("\n(figlio) ora aspetto 3 secondi\n");

for (i=0; i<3; i++) {

system("sleep 1"); printf(".\n");

}

printf("\n(figlio) invio un messaggio al padre e muoio\n");

msgp = &sndbuf;

msgp->mtype = 5;

strcpy(msgp->mtext,"BUONGIORNO");

msgsnd(msgid,msgp,sizeof("BUONGIORNO"),0);

exit(0);

}

puntatore alla struttura che contiene il messaggio

dimensione del messaggio

ininfluente

(11)

21

else /* processo padre */

{

msgp = &rcvbuf;

printf("\n(padre) leggo il messaggio del figlio");

printf("\nmi sospendo se non e' ancora arrivato\n");

i = msgrcv(msgid,msgp,100,5,0);

printf("\n(padre) messaggio ricevuto: %s\n",msgp->mtext);

printf("\n(padre) ora rimuovo la coda di messaggi e muoio\n");

msgctl(msgid,IPC_RMID,0);

exit(0);

} }

puntatore alla struttura che ospiterà il messaggio letto

massima lunghezza di messaggio leggibile

ricevo solo messaggi di tipo 5

se non ci sono messaggi del tipo specificato mi metto in attesa

22

output del programma msguse.c

prelevata coda di messaggi id = 100 (figlio) ora aspetto 3 secondi

(padre) leggo il messaggio del figlio,

mi sospendo se non è ancora arrivato .

.

(figlio) invio un messaggio al padre e muoio (padre) messaggio ricevuto: BUONGIORNO (padre) ora rimuovo la coda di messaggi e muoio

(12)

23

Visualizzare e rimuovere le risorse

$> ipcs

T ID KEY MODE OWNER

Message Queues:

q 10 0x003e8 --rw-r--r-- st103010

q 20 0x003e8 --rw-rw-r-- st102210

Shared Memory:

m 25 0x003e8 --rw-rw-rw- st103010

Semaphores:

s 280 0x003e8 --rw-rw-rw- st245020

$> ipcrm –q 10 –s 280 –m 25

• Le risorse non vengono deallocate quando il processo che le ha prelevate termina. Occorre farlo esplicitamente (con il comando o la system call opportuna)

Riferimenti

Documenti correlati

La Raccomandazione prevede che ciascuno Stato dell’Unione Europea, in base alle conoscenze scientifiche attuali, provveda affinché gli allevatori effettuino una

1973: UK, Irlanda e Danimarca entrano nell'UE Il governo inglese riteneva che fosse nel suo interessa far parte del processo di integrazione economica europea, in particolare per

Fermi / teoria dei giochi Plank / teoria quantistica Newton / caduta dei gravi Einstein / teoria della relatività Galileo / metodo sperimentale. &#34;Il cantante Tizio e' un cane;

E nonostante tutto cio' che sta accadendo ancora oggi, dopo un anno, penso che questa esprienza bruttissima ci cambierà tutti e che noi stiamo com- prendendo che

[r]

P er la prima volta il comune di Milano potrà avvalersi delle competenze e conoscenze di due medici veterinari come Garanti per la tutela degli animali. Paola Fossati e Gustavo

Con nota prot. 379 del 7 gennaio 2019, la Questura di Biella segnalava la necessità di ripristinare la tinteggiatura delle pareti e del soffitto degli alloggi di servizio al 2^

c) materiali di interesse marginale — materiali che costituiscono una distrazione per i suini ma che non dovrebbero essere considerati tali da soddisfare i loro