1 / 18

Architecture Système d’Unix II

Architecture Système d’Unix II. Exemple de fonctionnalités fournies par un système d’exploitation moderne Par Gilles Grimaud U niversité des S ciences et T echnologies de L ille http://www.lifl.fr/~grimaud/Cours. Plan du cours. 1. Les processus Unix ; Processus et signaux ;

tad-butler
Download Presentation

Architecture Système d’Unix II

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Architecture Système d’UnixII Exemple de fonctionnalités fournies par un système d’exploitation moderne Par Gilles Grimaud Université des Sciences et Technologies de Lille http://www.lifl.fr/~grimaud/Cours

  2. Plan du cours 1. Les processus Unix ; • Processus et signaux ; • Mémoire partagée ; • Gestion de la concurrence ; • Etreintes fatales.

  3. $p2 BashHello p2 : BashHello $p1 p2 : P1Hello $ exécution Les processus Unix Primitives fournies par le noyau :exec(char*)execl(), execv(), execle(), execve(), execlp(), execvp(). Exemple : /* programme p2 */int i; int main( int argc, char **argv) { /* ici i est sans rapport avec i ds p1 */ printf("p2 : %s\n",argv[1]); return 1; } /* programme p1 */int i; int main( int argc, char **argv) { char* argv[3]; argv[0]="p2"; argv[1]="P1Hello"; argv[2]=NULL; i = 1; execvp("p2",argv); fprintf(stderr, "exec failed\n"); return 0; }

  4. Les processus Unix Primitives fournies par le noyau : exec(char*) ... Mise en œuvre : Segment Text – p1 – Segment Text– p2 – Données initialisées Données initialisées Données vierges(BSS) Données vierges(BSS) Le tas Le tas La pile La pile Pile d’exécution Pile d’exécution Zone système Zone système Process p1 Process p2 exec()

  5. Les processus Unix Primitive fournie par le noyau : fork() Exemple de fonctionnement : int i; int main(int argc, char **argv) { int p = -1; i = 1; p = fork(); if( p == 0) /* processus fils */ i += 1; else /* processus père */ i += 2; printf("p=%d, i=%d",p,i); return i; } i : 1 p : -1 père i : 1 p : 3479 père Duplication environnements i : 1 p : 0 fils i : 3 p : 3479 père i : 2 p : 0 Process père Process fils fils

  6. Les processus Unix Primitive fournie par le noyau : fork() Mise en œuvre : Segment de Text – (Code –) Segment de Text – (Code –) Segment de Text – (Code –) Données initialisées Données initialisées Données initialisées Données vierges(BSS) Données vierges(BSS) Données vierges(BSS) Le tas Le tas Le tas La pile La pile La pile Pile d’exécution Pile d’exécution Pile d’exécution Zone système Zone système Zone système Process fils Process Process père fork()

  7. Processus et signaux Signaux  interruptions, au sein d’un processus • 32 types d’interruptions • 32 procédures différentes. • Les interruptions partagent le même environnement : • Même stdin/stdout/stderr • Même variables globales • Même tas, mémoire partagée • Les interruptions disposent : • Variables locales • Possibilité de dissocier la pile Réceptiond’un signald’interruption Procédure d’exceptionassociée àl’interruption Programme principal Fin de traitementdu signal

  8. Processus et signaux Les différents signaux : SIGABRT, SIGALRM, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, SIGTERM, SIGUSR1, SIGUSR2, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ. Envoyer un signal : if ( (pid = fork()) == 0 ) ... else kill(pid,SIGUSR1); Attendre un signal : pause();

  9. Processus et signaux Enregistrer une nouvelle procédure de traitement des interruptions : void cfunc(int sig) {printf("reception du signal SIGUSR1");} int main(int argc, char **argv) { struct sigaction siga; siga.sa_handler = SIG_DFL; sigemptyset(&siga.sa_mask); sigaddset(&siga.sa_mask, SIGUSR1 ); siga.sa_flags = SA_SIGINFO ; siga.sa_sigaction = cfunc; sigaction(SIGUSR1, &siga, NULL); printf("attente d’un signal...\n"); pause(); printf("signal reçus\n"); } Voir les primitives : sigemptyset(), sigfullset(), sigaddset(), sigdelset(), sigaction(), sigaction, sigxxx

  10. Mémoire partagée Unix Partager de la mémoire : • Plusieurs processus travaillent sur les mêmes données. Partage de segment de mémoire virtuelle via le système : • Enregistrer une page disposée à être partagée. • Obtenir une nouvelle page en partage. Processus 1 Processus 2 P P Mémoires virtuelles Mémoire physique Granularité d’une page

  11. Mémoire partagée Unix Préalable : Le fichier de prototype <sys/shm.h> est nécessaire pour pouvoir utiliser les mécanismes de partage de la mémoire. • Réclamer une page de mémoire partagée au système Unix (POSIX) : int shmget(key_t key, size_t size, int flag); Retourne un identifiant de mémoire partagée de taille size associé à la clef key. Valeur négative en cas de problème… 2. Attacher un segment de mémoire partagée au processus Unix : void *shmat(int shmid, const void *shmaddr, int flag); Retourne dans le processus courrant l’adresse de la page de mémoire virtuelle qui référence la mémoire partagée d’identifiant shmid. • Détacher un segment de mémoire partagée au processus Unix : int shmdt(void *shmaddr); Retourne -1 en cas de problème.

  12. Mémoire partagée Unix Exemple d’utilisation : /* partager de la mémoire */ id = shmget( 314159, sizeof(int), IPC_CREAT | 0666); if(id == -1) exit(1); /* error */ /* rechercher la mémoire partagé */ id =shmget( 314159, sizeof(int), 0666); if(id == -1) exit(1);/* error */ /* obtenir l’@ de partage */ intPtr = (int *)shmat(id,NULL,0); if( ((int)intPtr) == -1) exit(1); /* error */ /* lire et écrire */ printf(">>%x\n",*intPtr); *intPtr = 0xCAD0 ; /* rendre le segment partagé */ if(shmdt(intptr) == -1) exit(1); /* error */

  13. Gestion de la concurrence Lorsque plusieurs tâches « consomment » une certaine ressource, il peut être souhaitable de garantir que chaque accès à cette ressource soit fait de manière indépendante toutes les autres demandes de manipulations sont bloquées tant que la manipulation courante n’est pas terminée. Exemple : accès à un fichier, réservation de mémoire tampon pour des sockets, … Processus B Processus A Sémaphore P(3) val 5 P(4) Section contrôlée n°1 val 2 V(3) val 5 P(4) val 1 Section contrôlée n°2 V(4) val 5

  14. Création de sémaphores Unix Primitive de création d’une sémaphore : int semget(key_t key, int nsems, int semflg); Retourne un identifiant de semaphore ID (semid), ou -1. Les arguments : • key est une clef d’identification associée à la sémaphore créée. • nsems spécifie le nombre d’éléments dans la table de sémaphore. L’appel échoue quand nsems est plus grand que le nombre d’élément d’une table préexistante; Si se nombre n’est pas connu : utilisez 0 pour assurer que la fonction n’échoue pas. • semflg spécifie les permissions d’ accès et le flag de contrôle de création. Exemple : mysem = semget(3141,2,IPC_CREAT|IPC_EXCL|0660))

  15. Initialisation de sémaphores Unix Primitive de contrôle d’une sémaphore : int semctl(int semid, int semnum, int cmd, union semun arg); Retourne -1 en cas d’erreur. Les arguments : • semnum donne l’indexe de la sémaphore concernée. • cmd est une commande comme SETALL,IPC_RMID etc. • arg est optionnel, fonction de l’opération demandée. Si nécessaire, cet argument doit être explicitement déclaré comme suit : union semun { int val; struct semid_ds *buf; ushort *array; } arg; Exemple: ushort *init_val = (ushort *)malloc(4*sizeof(ushort)); for(i=0; i <4; i++) init_val[i] = 0; arg.array = init_val; if(semctl(mysem, 0, SETALL, arg) == -1) { perror("Error sem initialization"); exit(1); } Cet exemple initialise 4 sémaphores associées à mysem avec la valeur 0.

  16. Opération sur les sémaphores Unix Primitive d’exécution d’un ensemble opérations sur une table de sémaphores : int semop(int semid, struct sembuf *sops, size_t nsops); Retourne -1 en cas d’erreur. Les arguments sont : • semid est l’identifiant de sémaphore ID retourné par un appel précédent à semget(). • sops est un pointeur vers un tableau de structures. Chacune représente une opération relative aux sémaphore à exécuter. Chacune contient donc (i) Un numéro de sémaphore, (ii) Une opération à effectuer, (iii) des flags de contrôles si nécessaires. N.B. sembuf est un type définit comme suit : struct sembuf { ushort_t sem_num; /* (i) */ short sem_op; /* (ii) */ short sem_flag; /* (iii) */ } • nsops définit la taille du tableau d’opération.

  17. Opération sur les sémaphores Unix Exemple : static struct sembuf aquire = {0, -1, 0 /* IPC_NOWAIT */}, release = {0, 1, 0}; release.sem_num = 0; /* semaphore idx */ if(semop(mysem, &aquire, 1) == -1) { fprintf(stderr,"semop"); exit(1); } ... release.sem_num = 0; /* semaphore idx */ if(semop(mysem, &release, 1) == -1) { perror("semop"); exit(1); }

  18. Etreintes fatales P1 P’1 Réserve A Réserve B Si l’ordonnanceur fait P1,P’1,P2,P’2, P3, P’3, … Après P2 le processus P est bloqué (P attend que P’ libère B) Apres P’2 le processus P’ est bloqué aussi (P’ attend que P libère A). Chacun attend que l’autre libère une ressource  Etreinte fatale. Solution simple  numéroter les verrous et prendre les réservations par ordre croissants… réserver dans l’ordre croissant des indexes de la table de sémaphore par exemple… Autres solutions  détecter un inter-blocage et « annuler » l’une des reservations,  changer l’ordonnancement des tâches,  …etc Réserve B P2 Réserve A P’2 P3 P’3 Libère A Libère A Libère B Libère B P4 P’4

More Related