Documente Academic
Documente Profesional
Documente Cultură
12
Laborator nr. 12
Memoria partajata
key_t cheie;
int marime, permisii, shmid;
...
Sisteme de Operare Laborator nr. 12
shmid=shmget(cheie, marime, permisii);
...
La fel ca si la mesaje, cel mai important parametru este primul, cheie, cel care da
cheia de recunoastere globala a segmentului. Orice alt proces care vrea sa foloseasca
segmentul de memorie partajata, creat cu shmget, trebuie sa cunoasca aceasta cheie.
Cheia este, ca si mai inainte, de tipul key_t, dependent de implementare, dar de obicei un
long. Al doilea parametru, marime, este cel care specifica dimensiunea in octeti a
segmentului de memorie partajata care se doreste a fi cret. Ultimul parametru, permisii,
specifica drepturile de acces la segment. Apelul returneaza in shmid un identificator al
segmentului nou creat, care este local procesului. Daca apelul esueaza in crearea
segmentului de memorie partajata, este intoarsa valoarea -1, iar eroarea va fi
documentata in variabila globala errno. Valorile de eroare din errno sint dependente de
implementare. Trebuie consultat manualele on-line pentru functia shmget(S).
Daca marimea specificata la apel pentru segment este prea mare sau prea mica,
errno va fi setat pe valoarea EINVAL. Ce inseamna prea mic sau prea mare pentru
implementarea data, trebui de asemenea aflat.
Pentru specificarea permisiilor, se pot folosi valori asemanatoare cu cele pentru cozi
de mesaje. Trebuie deci specificate drepturile de acces la segment si citiva comutatori de
creare. De exemplu poate primi valoarea 066 | IPC_CREAT | IPC_EXCL, deci drepturi de
citire/scriere doar pentru proprietar, segmentul de memorie partajata va fi deschis numai
daca nu exista deja, caz in care va fi mai intai creat. Daca segmentul exista deja se va
intoarce valoarea de eroare -1.
Prin acest apel, a fost creat in memorie segmentul dorit. Accesul la el se va face in
continuare prin intermediul identificatorului sau, shmid. Acesta este local procesului
curent, deci nu va avea aceasi valoare si pentru alte procese care deschid aceeasi zona
de memorie partajata. La terminarea acestui apel segmentul nu este inca gata de a fi
folosit pentru procesul curent. Aceasta din cauza ca segmentul nu se gaseste inca in
spatiul de adresare al procesului. Pentru a atasa segmentul de memorie la proces exista
apelul shmat (attach shared memory). El poate fi apelat dupa cum urmeaza:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int comutatori,shmid;
char *adresa,*adresa_impusa;
...
adresa=shmat(shmid, adresa_impusa, comutatori);
...
Prin acest apel se creaza pentru procesul curent o adresa virtuala cu care se va
putea adresa in continuare zona de memorie partajata. Variabila adresa va contine dupa
apel aceasta adresa. Prin apel se poate forta si legarea segmentului la o anumita adresa
dorita, specificata prin parametrul adresa_impusa. Daca acest parametru are valoarea 0
si acesta este cazul comun, atunci sistemul va decide singur care este adresa unde va fi
legat segmentul si aceasta va fi urmatoarea adresa disponibila.
Se poate de asemenea impune ca segmentul sa fie atasat la o adresa care sa fie
inceput de pagina de memorie. Pentru aceasta trebuie specificata valoarea SHM_RND in
parametrul comutatori. Daca se impune o adresa de atasare, aceasta va fi rotunjita la
urmatorul inceput de pagina. Daca nu, va fi intors urmatorul inceput de pagina. Daca nu,
va fi intors urmatorul inceput de pagina disponibil. Alt comutator disponibil este
SHM_RDONLY, care specifica faptul ca segmentul trebuie protejat la scriere. Din pacate
numai acele configuratii hardware pot asigura o astfel de protectie. Daca parametrul
comutatori are valoarea 0, atunci accesul este si in citire si in scriere iar adresa nu va fi
Sisteme de Operare Laborator nr. 12
rotunjita in nici un fel.
Din acest moment acesul la segmentul de memorie este posibil prin adresa virtuala
adresa. Se poate scrie si citi din memorie variabile intregi prin instuctiuni de genul:
int i, *pint;
pint=(int *)adresa;
*pint++=i;
...
i=*pint;
...
Sau se poate adresa segmentul caracter cu caracter in felul urmator:
int i;
for(i=0;adresa[i];i++)
...;
Dupa terminarea lucrului cu memoria partajata aceasta trebuie desigur eliminata din
spatiul de adresare al procesului. Acest lucru se face cu ajutorul apelului shmdt (detach
shared memory). Acesta se apeleaza astfel:
...
retur=shmdt(adresa);
...
Dupa acest apel nu se mai poate adresa in nici un fel segmentul de memorie
partajata, decit dupa o noua atasare. In clipa in care toate procesele care aveau nevoie de
segmentul de memorie partajata s-au detasat de la acesta, segmentul poate fi distrus
complet printr-un apel shmctl. Apelarea se face astfel:
...
retur=shmctl(shmid, IPC_RMID, 0);
...
$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 1627649 user 640 25600 0
Pentru a sterge zona de memorie afisata mai sus se foloseste comanda ipcrm:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY (key_t)100
/* scrie.c */
#include "shmen.h"
int shmid;
main()
{
int i;
char *adresa;
extern cleanup();
i=0;
while(1)
{
/*legarea in spatiul de adrese*/
adresa=shmat(shmid, 0, 0);
/* citeste.c */
#include "shmen.h"
int shmid;
main()
{
int i,*pint=0;
char *adresa;
while(*pint==0);
/*nu citeste pina nu este gata driverul*/
Sisteme de Operare Laborator nr. 12
/*citirea mesajului*/
printf("%s\n",adresa);
Exemplul 2:
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
int main ()
{
int segment_id;
char* shared_memory;
struct shmid_ds shmbuffer;
int segment_size;
const int shared_segment_size = 0x6400;
Bibliografie:
• Iosif Ignat, Adrian Kacso, UNIX Gestionarea Proceselor, Ed. Albastră, 2006
• W. Richard Stevens, Stephen A. Rago, Advanced Programming in the UNIX Envi-
ronment: Second Edition, Addison Wesley, 2005
• Kurt Wall, Mark Watson, and Mark Whitis, Linux Programming Unleashed, Sams
Publishing, 1999
• A. D. Marshall, Programming in C. UNIX System Calls and Subroutines using C,
http://www.cs.cf.ac.uk/Dave/C/
• Guide to Unix IPC http://beej.us/guide/bgipc/output/html/singlepage/bgipc.html
Sisteme de Operare Laborator nr. 12
• Mark Mitchell, Jeffrey Oldham, and Alex Samuel, Advanced Linux Programming,
New Riders Publishing, 2001, http://www.advancedlinuxprogramming.com/
• Compiler, assembler, linker and loader: a brief story
http://tenouk.com/ModuleW.html