Programmation Système
TP n° 4
(Mémoire partagée)




Notions abordées :


Exercice 1.

Ecrire un programme qui crée une mémoire partagée (un int) et qui crée un fils. Le père écrit la valeur 0 dans cette zone de mémoire partagée et attend que la valeur soit égale à 1. Quand c’est le cas, il affiche "Ok, je termine !" et il termine. Le fils attend une seconde, écrit la valeur 1 dans cette cette zone de mémoire partagée et termine. Faire attention à ce que la mémoire partagée soit bien libérée à la fin de l'exécution du programme. NB: On prendra pour clé la valeur IPC_PRIVATE puisque la mémoire partagée n'est utilisée que par le processus courant et sa descendance.

Exercice 2.

Même chose que l'exercice 1 mais avec deux programmes indépendants : Le premier programme crée une mémoire partagée (un int), écrit la valeur 0 et attend que la valeur soit égale à 1. Quand c’est le cas, il affiche "Ok, je termine !" et il termine. Le deuxième programme attend une seconde, écrit la valeur 1 et termine. Faire attention à ce que la mémoire partagée soit bien libérée à la fin de l'exécution du premier programme. NB: On utilisera la fonction ftok pour générer une clé qui identifie de manière unique la mémoire partagée.

Exercice 3.

Ecrire un programme où deux processus effectuent concurremment la somme C de deux matrices carrées A et B : Les 3 matrices seront stockés dans une zone de mémoire partagée. Si je suis le père, je remplis la matrice A, j'attends que le fils ait remplit la matrice B (important !) et je calcule la somme C[i,j] = A[i,j]+B[i,j]  pour tous les indices i pairs; si je suis le fils, je remplis la matrice B, j'attends que le père ait remplit la matrice A et je calcule la somme C[i,j] = A[i,j]+B[i,j] pour tous les indices i impairs. On fera également l’affichage de la matrice résultat C (à votre avis, dans le père ou dans le fils ?). NB: Il faut donc trouver un moyen pour que les processus s'attendent (on dit aussi "se synchronisent") : On pourra utiliser les signaux ou bien la mémoire partagée comme dans l'exercice 1.  

Exercice 4.

Même question que dans l'exercice 3 pour le produit de matrices carrées (on rappelle que C[i,j] = ∑k A[i,k]*B[k,j]) : les processus père et fils calculent alternativement une ligne du résultat selon que l’indice des lignes dans la matrice résultat est pair ou impair. A votre avis, est-ce que votre code fait des accès concurrents en lecture à la mémoire ? Est-ce gênant ?

Exercice 5.

Soient les deux processus P1 et P2 suivants qui s'exécutent concurremment et qui accèdent à la variable commune (partagée) N :
processus P1:       processus P2: 
.....               .....  
load r1, N          load r2,N 
add r1,r1, 1        add r2,r2,1 
store r1,N          store r2, N 
exit                exit 
Vous savez qu'une instruction de type N = N+1 n'est pas atomique (l'ordonnanceur peut passer la main à un autre processus avant qu'elle se termine). Donnez deux scénarios d'exécution de P1 et P2 qui conduisent à deux valeurs distinctes pour N lorsque P1 et P2 sont terminés.

Vous pouvez construire vos scénarios en composant un programme avec les instructions de P1 et les instructions de P2; mais en préservant l'ordre interne des opérations (vous ne pouvez pas faire dans cet ordre un store r1,N puis load r1, N). En mélangeant les instructions de la sorte, combien de programmes pouvez-vous construire ?

Exercice 6.

On rappelle que la fonction log(x+1) peut être approchée par le développement suivant à l’ordre 12 :

x-1/2*x^2+1/3*x^3-1/4*x^4+1/5*x^5-1/6*x^6+1/7*x^7-1/8*x^8+1/9*x^9-1/10*x^10+1/11*x^11+O(x^12)

et pour -1 < x <= 1, x étant un réel.

Ecrire un programme à deux processus qui lit une valeur pour x et un ordre de grandeur k et qui calcule log(x+1) à l’ordre k avec la formule précédente : le père calcule les puissances paires et le fils les puissances impaires. Vous pouvez appliquer l’algorithme suivant :

a) Le père (seul) commence par ranger dans un tableau T partagé les puissances : T[0]=1, T[1]=x, T[2]=x*x, T[3]=x*x*x…

b) Le père et le fils multiplient chacune des puissances par le coefficient approprié (père traite les puissances paires, le fils les puissances impaires) afin de calculer les sommes partielles ;

c) Il reste a faire la somme des deux sommes partielles (par le père ou le fils ?) et d’afficher le résultat.

Un autre algorithme est possible. Contrairement au précédent, la première phase (calcul des T[i]) peut être réalisée par le père et le fils sous les contraintes suivantes : le père calcule les T[i] pour i pairs, le fils les T[i] pour les i impairs. Cependant on ne peut produire T[i] que si T[i-1] a été produit en faisant T[i]=T[i-1]*x. Cela séquentialise le code et fait intervenir des synchronisations entre le père et le fils. La synchronisation entre le père et le fils peut s'implémenter par le pseudo code suivant (on initialise une variable semaphore à 1 juste avant le fork – semaphore est une variable en mémoire partagée):

Processus exécuté par le père : 
Etiq1:
  while(est_impair(semaphore)) attendre;
  T[semaphore] = T[semaphore-1]*x;
  semaphore++;
  goto Etiq1;
Processus exécuté par le fils : 
Etiq2:
  while(est_pair(semaphore)) attendre;
  T[semaphore] = T[semaphore-1]*x;
  semaphore++;
  goto Etiq2;

Note : ci-dessus les processus sont dans une boucle infinie : le contrôle sur le nombre d'itérations à effectuer n'est pas fait !

Exercice 7.

Dans l'exercice précédent, l'instruction T[semaphore] = T[semaphore-1]*x; constitue la section critique c'est-à-dire le code qui ne peut être accédé que par au plus un processus. Recoder l'exercice précédent au moyen de l'algorithme de Peterson suivant qui assure l'exclusion mutuelle :
shared boolean wantIn[2]=false,false;
shared int turn;

int myPid = 0; //pour le processus pere et init à 1 pour le fils
int otherPid = 1 – myPid;
while(true){
   wantIn[myPid] = true;
   turn = otherPid;
   while !((wantIn[otherPid] == false) || (turn == myPid)) DoNothing();
   // section critique
   wantIn[myPid] = false
}
Expliquer ensuite de manière intuitive pourquoi ce code garantit un accès exclusif à la portion de code dite « section critique ».