Documente Academic
Documente Profesional
Documente Cultură
11
Laborator nr. 11
1. Cozi de mesaje
Sincronizarea între procesele care transmit mesaje si cele care receptioneazã se
face pe principiul producator/consumator, controlat de nucleul sistemului de operare. Acest
principiu precizeaza ca procesul producator se blocheaza daca coada de mesaje este
plina, pâna când un proces consumator preia un mesaj. La fel, procesul consumator se
blocheaza daca coada de mesaje este goala sau daca nu are în coada un mesaj transmis
lui, pâna când un proces producator îi transmite un mesaj.
Procesul care doreste sa transmita un mesaj obtine pe baza cheii numerice ID-ul
cozii prin apelul funcþiei msgget, iar apoi scrie mesajul în coada, apelând functia
msgsnd. Mesajele sunt adaugate la sfârsitul cozii.
Procesul care doreste sa receptioneze un mesaj din coada obtine pe baza cheii
numerice ID-ul cozii prin acelasi apel al functiei msgget, iar apoi citeste mesajul din coada
prin apelul functiei msgrcv. Receptionarea mesajelor din coada se poate face dupa
câmpul mtype nu neaparat dupa regula primul intrat primul iesit.
Structura unui mesaj este definitã în fisierul msg.h sub forma:
struct msgbuf {
long mtype;
char mtext[1];
};
Primul câmp al structurii, mtype, contine un numar întreg lung care precizeaza tipul
mesajului. Din acest motiv s-a lasat neutilizat acest câmp la exemplele prezentate la
fisierele FIFO. Dupa acest câmp urmeaza mesajul propriu-zis, care este redus la un singur
caracter. Daca mesajul care se doreste a fi trimis se presupune a fi de 256 octeti se poate
defini o alta structura sub forma:
struct msg {
long tip;
char continut_mesaj[256];
};
Structura mesajului cu care lucreaza o aplicatie nu este impusa. Ea trebuie sa
contina doar tipul mesajului si mesajul propriu-zis, a carui dimensiune este functie de
aplicatie.
Fiecare coada are asociata urmatoarea structura msqid_ds:
struct msqid_ds {
struct ipc_perm msg_perm; /* vezi mai jos */
struct msg *msg_first; /* pointer la primul mesaj */
struct msg *msg_last; /* pointer la ultimul mesaj */
ulong msg_cbytes; /* octeþi în coadã */
ulong msg_qnum; /* nr. mesaje în coadã */
ulong msg_qbytes; /* nr.max.de octeþi din coadã*/
pid_t msg_lspid; /* pid-ul ultimului msgsnd() */
Sisteme de Operare Laborator nr. 11
pid_t msg_lrpid; /* pid-ul ultimului msgrcv() */
time_t msg_stime; /* timpul ultimului msgsnd() */
time_t msg_rtime; /* timpul ultimului msgrcv() */
time_t msg_ctime; /* timpul ultimei modificãri a structurii
prin apelul funcþiei msgctl */
};
Cei doi pointeri nu sunt utili programelor utilizator, ei refera adresele unde sunt
stocate mesajele în nucleu.
Un proces poate avea acces la o coada de mesaje daca:
• procesul este al superuser-ului;
• ID utilizatorului, uid, coincide cu msg_perm.cuid sau cu msg_perm.uid si este
prevazut în msg_perm.mode dreptul de acces dorit;
• utilizatorul are ID de grup, gid, identic cu msg_perm.cgid sau cu
msg_perm.gid si este prevazut în msg_perm.mode dreptul de acces dorit;
• utilizatorul face parte din categoria "alti utilizatori" si este prevazut în
msg_perm.mode dreptul de acces dorit.
4. Probleme rezolvate
4.1. Pentru a exemplifica folosirea cozilor de mesaje se va compila si rula exemplul
prezentat in continuare. Functiile send si receive se vor rescrie folosind functiile msgsnd
si msgrcv de la mesaje.
Functia care gestioneaza cozile de mesaje este openqueue care, în acest caz,
este mult mai simpla, deoarece cozile de mesaje nu sunt o resursa limitata ca descriptorii
de fisier.
Toate mesajele trimise sunt de tipul 1 si procesul care transmite, respectiv
receptioneaza un mesaj este blocat daca coada este plina, respectiv goala. Acest lucru
este posibil deoarece, spre deosebire de fisierele FIFO, procesul care transmite mesajul
poate sa-l depuna în coada fara a astepta procesul receptor.
Codul fisierului mesaj.c este ilustrat în cele ce urmeaza:
/******************** MESAJ.C ********************/
#include <sys/ipc.h>
Sisteme de Operare Laborator nr. 11
#include <sys/msg.h>
#include "hdr.h"
4.2. Un proces server ofera câteva servicii pe care un proces client le poate solicita
printr-un mesaj.
Structura mesajului de cerere, cheia cozii si codurile ce identifica un anumit serviciu
sunt declarate în fisierul mes.h, care este inclus de programele clientului si serverului.
Sisteme de Operare Laborator nr. 11
void consumer()
{
message cmsg;
while (true)
{
receive (mayconsume, cmsg);
consume (cmsg);
send (mayproduce, null);
}
}
void main()
{
create_mailbox (mayproduce);
create_mailbox (mayconsume);
for (int i = 1; i <= capacity; i++)
send (mayproduce, null);
parbegin (producer, consumer);
}
Writer(j){
rmsg = j;
send( writerequest, rmsg );
receive( mbox[j], rmsg );
writer C.S.
rmsg = j;
send( finished, rmsg );
}
Controller () {
do forever
if ( count > 0 )
if ( !empty( finished ) )
Sisteme de Operare Laborator nr. 11
receive( fininshed, msg );
count++;
else if ( !empty( writerequest ) )
receive( writerequest, msg );
writer_id = msg.id
count -= 100;
else if ( !empty( readrequest ) )
receive( readrequest, msg );
count--;
send( msg.id, “OK” );
if ( count == 0 )
send( writer_id, “OK” );
receive( finished, msg );
count = 100;
while ( count < 0 )
receive( finished, msg );
count++;
}
6. 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
• 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