Aritoni Ovidiu Sisteme de operare 1 Introducere


Terminarea unui proces Windows



Yüklə 486,94 Kb.
səhifə27/27
tarix12.01.2019
ölçüsü486,94 Kb.
#96236
1   ...   19   20   21   22   23   24   25   26   27

Terminarea unui proces Windows
Un proces poate fi terminat pe două căi:

  • apelând din interior funcţia EixtProcess

sau

  • aplând din exterior funcţia TerminateProcess.

Este preferabilă prima cale, cea de-a doua trebuie folosită doar pentru situaţii

extreme.
Prototipul funcţiei ExitProcess este:
VOID ExitProcess (UINT fuExitCode);

Funcţia termină procesul care a apelat-o şi îi setează acestuia codul de retur pe valoarea fuExitCode.


Funcţia TerminateProcess are următorul prototip:

BOOL TerminateProcess (HANDLE hProcess, UINT fuExitCode);


Cu această funcţie, un proces poate termina orice alt proces din sistem, inclusiv pe el însuşi. Procesul teminat este dat de referinţa hProcess. Codul de retur a procesului terminat va fi setată pe valoarea parametrului fuExitCode. Folosirea funcţiei TerminateProcess poate fi periculoasă la o programare neîngrijită. În mod normal, evenimentul de terminare a unui proces este semnalat de către Windows NT tuturor DLL-urilor ataşate de proces. La terminarea procesului, folosind funcţia TerminateProcess, aceste DLL-uri nu vor fi avertizate, producându-se eventuale pierderi de date. Windows NT garantează totuşi că toate resursele sistem utilizate de proces vor fi eliberate indiferent cum este terminat procesul.

Exemplu de creare proces sub Windows
Exemplul care urmează este similar celui din Programul 3.3. Aplicaţia consolă creează un proces fiu, în care se va face rezumatul directorului curent, lansând în acest scop comanda sistem dir.

Înainte de a prezenta programul DirWindows.cpp, introducem rutina err_sys, corespunzătoare sursei 3.1, de data aceasta, în două variante (Programul 3.8.). La fel ca sub Unix, vom folosi una din cele două funcţii err_sys, în cazul unor diverse apeluri de funcţii Windows, care eşuează.


#include
//afiseaza textul si termina programul

int err_sys (char *text) {

puts (text);

exit (1);

} //er_sys

Programul 3.8. Sursele err_sys.cpp
(Sub unele implementări, rolul funcţiei noastre err_sys poate fi preluat de către un apel sistem numit perror.)

Programul 3.9. prezintă sursa DirWindows.cpp.


#include Ţstdafx.hŢ

#define STRICT

#include

#include

#include “err_sys.cpp”
int main ( ) {
STARTUPINFO si = { sizeof (si) };

PROCESS_INFORMATION pi;

BOOL b = CreateProcess (“rezumat.bat”, NULL,

NULL, NULL, FALSE, 0, NULL, NULL

&si, &pi);

if ( b ) {

// Asteapta procesul sa-si inceapa executia (v. mai jos)

Sleep (1000);

// Am considerat necesar acest timp de asteptare pt.

// a permite sistemului sa creeze procesul inainte

// de a testa terminarea lui

if (TerminateProcess (pi.hProcess, 2) ) {

DWORD dwT, dwP;

GetExitCodeProcess (pi. hProcess, &dwP);

// obtine codul de retur al thread-ului principal

GetExitCodeThread (pi.hThread, &dwT);

if ( dwT ! = 2 )

printf (“Cod de retur incorect pentru proces”);

if ( dwT ! = 2)

printf (“Retur incorect pentru thread principal”);

CloseHandle (pi. hProcess);

CloseHandle (pi. hThread);

Printf (“\nExecutie cu succes\n”);
}

else


err_sys (GetLastError ( ) );

}

else



err_sys (“eroare la lansare rezumat.bat\n”);

return 0;

}
Programul 3.9. Sursa DirWindows.cpp
Precizăm că dacă procesul creat îşi încheie execuţia înainte de apelul TerminateProcess ( ), acest apel returnează ERROR_ACCESS_DENIED.

Lănsăm pe seama cititorului să modifice acest exemplu, scriind un program propriu care să fie lansat în cadrul procesului fiu.



Anexa 2 Pipe sub Windows NT

În Windows NT, există două posibilităţi de a folosi pipe în IPC. O primă variantă este pipe anonime, care se pot folosi numai pentru comunicarea între procese de pe aceeaşi maşină. A doua variantă este pipe cu nume, folosite pentru comunicarea între procese ce operează nu neapărat pe aceeaşi maşină NT.



Pipe anonim Windows
Ne vom ocupa mai întâi de pipe anonime, ca şi mecanism IPC în programarea concurentă sub Windows NT. Un pipe anonim poate fi folosit, ca şi pipe-ul de sub Unix, pentru comunicarea între procese descendente din creatorul pipe-ului. În urma creării, procesul creator poate trimite fiilor (nepoţilor etc.) handle-urile pipe-ului, în momentul creării proceselor fii prin apeluri ale funcţiei CreateProces ( ) (vezi 3.1.3.3). Pentru ca fiul să moştenească handle-ul la pipe, părintele trebuie să seteze parametrul fInheritHandle, din apelul CreateProces ( ), la valoarea TRUE.

Un pipe fără nume se creează folosind apelul CreatePipe ( ). Pipe-ul se închide cu ajutorul funcţiei CloseHandle ( ). Funcţia CreatePipe ( ) creează un pipe fără nume şi are următorul prototip:

BOOL CreatePipe (PHANDLE phRead, PHANDLE phWrite,

LPSECURITY_ATRIBUTES lpsa,

DWORD cbPipe )ş

Funcţia întoarce TRUE în caz de succes sau FALSE la eşec.


phRead şi phWrite
Sunt pointerii spre cele două handle-uri (de citire şi de scriere) obţinute în urma creării.
lpsa - Parametrul are o dublă semnificaţie: determină dacă handle-ul la pipe, returnat de funcţie poate fi moştenit în procesele fii, proprietate care are loc pentru o valoare diferită de NULL. Acelaşi parametru reprezintă un descriptor de securitate. Dacă se specfică pentru acest parametru valoarea NULL, sistemul va fixa atributele de securitate implicite.
cbPipe - Specifică dimensiunea buferului rezervat pentru operaţiile de I/O prin

pipe. Dacă această valoare este 0, atunci dimensiunea implicită a

buferului o stabileşte sistemul de operare.
Scrierea şi citirea din pipe-urile anonime se face folosind funcţiile ReadFile ( ) şi WriteFile ( ). Prototipurile acestora sunt date în 3.2.3.2. Operaţiile sunt atomice. O citire va opri procesul până când va reuşi să se execute. În mod similar, o scriere va bloca procesul până când va avea suficient spaţiu în pipe pentru efectua operaţia de scriere dorită.

Atât procesul creator, cât şi procesele fii care moştenesc cele două handle-uri ale pipe-ului, le pot folosi între momentul primirii lor şi momentul închiderii. Astfel, procesul creator poate începe imediat să folosească pipe prinapelurile ReadFile ( ) şi WriteFile ( ). După creare şi primirea handle-urilor, procesele fii pot să folosească la rândul lor funcţiile ReadFile ( ) şi WriteFile ( ) pentru a citi sau scrie din pipe.

Următorul exemplu, o nouă soluţie a problemei propoziţiilor (3.2.1.2.), demonstrează modul de folosire al pipe-urilor anonime între un proces părinte şi procesul său fiu. Pipe-ul anonim şi procesul fiu sunt astfel create încât fiul să moştenească de la părinte handle-ul de citire. Programul PropozitiiPipeScriitor.cpp citeşte de la intrarea standard liniile de text şi le depune în pipe. Programul PropozitiiPipeCititor.cpp primeşte de la părinte handle-ul de citire din pipe, citeşte din pipe şi afişează propoziţiile la ieşirea lui standard.

Procesul părinte creează un pipe anonim şi un proces fiu, căruia îi trimite, prin linia de comană, handle-ul de citire din pipe. Apoi îi depune în pipe succesiunea de linii citite de la intrarea lui standard. Programul 3.26 prezintă sursa acestuia, iar Programul 3.27 sursa


PropozitiiPipeCititor.cpp.
# include

# include

# include

# include

# include “err_sys.cpp”

# include “scriitorInPipe.c”

# define MESSAGE_SIZE 1000

int cdecl main (int argc, char **argv) {


DWORD dwCodDeReturn, dwOctetiCititi;

int iFiu, iContor;

SECURITY_ATTRIBUTES saAtribute:

STARTUPINFO siInfo;

PROCESS_INFORMATION piFiu;

HANDLE hPipeCitire, hPipesScriere;


// Configurarea atributelor de securitate

// cu care pipe/ul va fi mostenit

memset (&sAtribute, 0xoo, sizeof (SECURITY_ATTRIBUTES) );

saAtribute.nLength = sizeof (SECURITY_ATTRIBUTES);

saAtribute.bInheritHandle = TRUE;
// Crearea unui pipe anonim

if (CreatePie (&hPipeCitire, // Handle de citire din pipe

&hPipeScriere, // Handle pentru scrierea in pipe

&saAtribute, // Atribute de securitate

MESSAGE_SIZE // Dimensiune bufer pentru pipe

) = = False)

err_sys (“Eroare la creare pipe\n”);
// Trimite clientului handle de pipe prin care sa poata citi

// prin crearea corespunzatoare a liniei de comanda

TCHAR wszLiniaDeComanda [ MAX_PATH ];

sprintf ( wszLiniaDeComanda, “fiu %d”, hPipeCitire);


// Creare proces fiu

memset ( &siInfo, 0x00, sizeof (STARTUPINFO) );

siInfo.cb = sizeof (STARTUPINFO);

siInfo.lpTitle = “Proces fiu”;

if (CreateProcess (NULL, // Pointer la nume modul executabil

wszLiniaDeComanda, // Linia de comanda

&saAtribute, // Atrib. de securitate pt. proces

&saAtribute, // Atrib. de securitate pt. thread

TRUE, // mosteneste toate handle-urile

CREATE_NEW_CONSOLE, // Atrib. suplimentare

NULL, // Variabila de mediu

NULL, // Directorul curent

&siInfo, // Informatii start

&piFiu // Aici returnare informatii

// despre procesul fiu

) = = FALSE)

err_sys (“Eroare la crearea procesului fiu \n”);
scriitorInPipe (hPipeScriere);
// Asteapta sa termine procesul fiu

do {
if (GetExitCodeProcess (piFiu.hProcess,

&dwCodDeReturn) = = FALSE)

err_sys (“Eroare la GetExitCodeProcess\n”);


if (dwCodDeReturn = = STILL_ACTIVE)

Sleep (1);

} while (dwCodDeReturn = = STILL_ACTIVE);

CloseHandle (hPipeScriere);

Return (0);

}
Programul 3.26. Sursa PropozitiiPipeScriitor.cpp


#include #include

#include

#include

#include “cititorDinPipe.c”
int cdecl main (int argc, char **argv) {

HANDLE hPipeCitire;

// obtine un handle de citire din pipe

hPipeCitire = (HANDLE) atol (argv [1]);


// apeleaza rutina de citire din pipe

cititorDinPipe (hPipeCitire);

CloseHandle (hPipeCitire);

return (0);

}
Programul 3.27. Sursa PropozitiiPipeCititor.cpp

Pipe cu nume sub windows


Pipe cu nume este un mecanism de comunicare între două sisteme diferite, ambele fiind operaţionale pe platforme din clasa Microsoft: Windows 95, 98, 2000, NT, precum şi platforme mai vechi, ca OS/2, Novell, DOS (numai client). Este un IPC bidirecţional, cu facilităţi apropiate de cele ale comunicării prin socket [11].

În figura 3.10 sunt prezentate succesiunile apelurilor sistem, atât pentru server, cât şi pentru client. Cititorul poate uşor observa particularizările necesare pentru comunicarea prin pipe anonim.




  1. CreateNamedPipe

  2. ConnectNamedPipe

  3. ReadFile 1. CreateFile

  4. WriteFile 2. ReadFile

  5. DisconnectNamedPipe 3. WriteFile

  6. CloseHandle 4. CloseHandle


Server

Server

Pipe cu nume


Figura 3.10. Comunicarea prin pipe cu nume sub Windows
Crearea unui pipe cu nume se face prin apelul sistem:
CreateNamedPipe,
cu prototipul:
HANDLE CreateNamedPipe (

LPSTR numePipe,

DWORD optiuniModOpen,

DWORD optiuniModPipe,

DWORD nMaxInstances,

DWORD lungBufOut,

DWORD lungBufIn,

DWORD timeOut,

LPSECURITZ_ATTRIBUTES lpsa

)
unde:


numePipe

Este un string prin care se indică numele pipe-ului.

Convenţiile Microsoft de specificare a acestor nume impun două sintaxe, una pentru pipe local şi alta pentru pipe de pe o altă maşină. Aceste specificări sunt:
\\.\PIPE\numePipePeMAsina

\\adresaMasina\PIPE\numePipePeMasina


adresa maşinii este fie o specificare Internet, fie o adresă IP [1].

Atenţie! În constantele string de specificare a acestor nume, fiecare caracter \ trebuie dublat, aşa cum cer regulile de evitare specifice limbajului C.
optiuniModOpen
Specifică direcţia de deschidere a pipe-ului. Valoarea lui poate fi una dintre constantele:
PIPE_ACCESS_DUPLEX,

PIPE_ACCESS_INBOUND,

PIPE_ACCESS_OUTBOUND,
indicând fie ambele sensuri, fie numai de la client la server, fie numai de la server spre client.
optiuniModPipe
Precizează caracteristicile acestui pipe. Pentru specificare, se folosesc constante sau combinaţii legate între ele prin operatorul “|”.



  • PIPE_TYPEBYTE, PIPE_TYPE_MESSAGE pentru scrierea ca flux de octeţi,

respectiv ca şi mesaj;

  • PIPE_READMODE_BYTE, PIPE_READMODE_MESSAGE pentru citirea după regulile fluxului de octeţi sau citirea ca şi mesaj;

  • PIPE_WAIT, PIPE_NOWAIT pentru comunicarea sincronă, respectiv asincronă.

nMaxInstances

Specifică numărul de clienţi care se vor conecta la acest pipe. La nevoie, se poate folosi constanta
PIPE_UNLIMITED_INSTANCES.
lungBufOut şi lungBufIn
Specifică dimensiunile bufferelor, pentru ieşire şi intrare. Sistemul ia aceste numere doar ca sugestii, în funcţie de context el putând să redimensioneze aceste buffere.
timeOut

Indică, în milisecunde, durata maximă de aşteptare.


lpsa
Specifică atributele de securitate. De cele mai multe ori se specifică NULL, lăsând astfel pe seama sistemului fixarea acestora.

Apelul sistem întoarce un handle, care va fi folosit ca şi argument în celelalte apeluri sistem legate de pipe.

După crearea unui pipe cu nume, serverul apelează:
ConnectNamedPipe (HANDLE hNamedPipe; LPOVERLAPPED lpo=
Primul handle este cel întors de crearea pipe. Al doilea parametru, de regulă NULL,

indică faptul că se aşteaptă la conectare până când un client se conectează efectiv la pipe. (A se compara această regulă cu cea similară de la FIFO de sub Unix).

La fel ca şi la pipe anonime, se folosesc apelurile ReadFile şi WriteFile pentru schimbul cu pipe.

Serverul îşi încheie activitatea apelând:


DisconnectNamedPipe (HANDLE hNamedPipe);

CloseHandle )HANDLE hNamedPipe);


Pentru client, conectarea la un pipe cu nume presupune un apel sistem
CreateFile

Descriem aici, prototipurile funcţiilor de lucru cu fişiere sub Windows.


HANDLE CreateFile (

LPCTSTR numeFisier,

DWORD acces,

DWORD partajare,

LPSECURITY_ATTRIBUTES descr_sec,

DWORD mod_deschid,

DWORD atributeFisier,

HANDLE fis_atrib

);
unde:
numeFisier - Este numele fişierului care se va crea.

acces - Este modul de acces (în citire şi/sau scriere).

partajare - Este modul de partajare a fişierului.

mod_deschid - Este modul de creare a fişierului.

atributeFisier - Sunt atribute fi;ier.
În cazul creării unui pipe cu nume, numeFisier reprezintă numele pipe-ului, cu sintaxa specificată mai sus, la apelul CreateNamedPipe.
HFILE OpenFILE (

LPCSTR numeFisier,

LPOFSTRUCT lpBuf,

UINT uActiune

);
unde:
numeFisier – Este numele fişierului care se va deschide.

lpBuf - Este pointer la o structură care reţine informaţii despre fişier.

uActiune - Indică operaţia care se va efectua asupra fişierului.
BOOL WriteFile (

HANDLE hFisier,

LPCVOID lpBuf,

DWORD nNrOctetiDeScris,

LPDWORD lpNumarOctetiScrisi,

LPOVERLAPPED lStructIO

);
unde:
hFisier - Este handle-ul fisierului în care se va scxrie.

lpBuf - Este pointer la datele care se vor scrie în fişier.

nNrOctetiDeScris - Este numă de octeţi de scris.

1pNumarOctetiScrisi - Este pointer la numărul de octeţi scrişi efectiv.

lpStructIO - Este de obicei are valoarea NULL.
BOOL RedaFile (

HANDLE hFisier,

LPCVOID lpBuf,

DWORD nNrOctetiCititi,

LPOVERLAPPED lpStructIO

);

unde:


hFisier - Este handle-ul fişierului din care se va citi.

lpBuf - Este pointer la un bufer în care se vor citi datele.

nNrOctetiDeScris - Este număr de octeţi de citit.

lpNumarOctetiCititi - Este pointer la numărul de octeţi citiţi efectiv.

lpStructIO - Este de obicei are valoarea NULL.

BOOL CloseHandle (HANDLE hObject);


unde:
hObject - Este handle-ul la un obiect deschis.

Pentru mai multe informaţii legate de prototipurile acestor funcţii, se recomandă consultarea documentaţiei MSDN [83].

Drept exemplu de utilizare a acestui pipe, vom da încă o soluţie a problemei propoziţiilor. Considerăm că atât programul scriitor (în pipe), cât şi programul care citeşte din pipe se găsesc pe aceeaşi maşină.

Spre deosebire de pipe sub Unix, în cazul Windows creatorul resursei pipe trebuie să fie activ, pentru ca eventualii scriitori sau cititori să poată comunica folosind pipe-ul respectiv. De aceea, vom include operaţia de creare a pipe-ului în programul care scrie date în pipe.

Programul 3.28 indică sursa scriitorului în pipe (care este şi creatorul resursei pipe), iar Programul 3.29 indică sursa cititorului din pipe.
#include “scriitorInPipe.c”

#include

#include ”err_sys.cpp”
main ( ) {
Handle hNamedPipe;
// creeaza pipe/ul cu numele „propoz”

hNamedPipe =

CreateNamedPipe (\\\\.\\PIPE\\propoz,

PIPE_ACCESS_OUTBOUND | FILE_FLAG_WRITE_THROUGH,

PIPE_TYPE_BYTE | PIPE_WAIT, 3, dimBufIn, DimBufOut, TMOUT, NULL);

err_sys (hNamedPipe! = INVALID_HANDLE_VALUE);


// asteapta sa se conecteze un client

ConnectNamedPipe (hNamedPipe, NULL);


// apeleaza rutina de scriere in pipe

scriitorInPipe (hNamedPipe);

DisconnectNamedPipe (hNamedPipe);

CloseHandle (hNamedPipe);

}
Programul 3.28. Sursa PropozitiiFifiScriitor.cpp
#include

#include

#include ”cititorDinPipe.c”

#include ”err_sys.cpp”


main ( ) {
HANDLE hNamedPipe;
// deschide pipe/ul in citire

hNamedPipe =

CreateFile (*\\\\.\\PIPE\\propoz”,

GENERIC_READ, FILE_SHARE_READ, NULL,

OPEN_EXISTING, 0, NULL);

err_sys (hNamedPipe! = INVALID_HANDLE_VALUE);


// apeleaza rutina de citire din pipe

cititorDinPipe (hNamedPipe);

ClosedHandle (hNamedPipe);

}
Programul 3.29. Sursa PropozitiiFifoCititor.cpp


Invităm cititorul să construiască programele corespunzătoare surselor 3.22. (SemnaturaFifoScriitor.c) şi 3.23 (SemanaturaFifoCititor.c), în cazul mecanismului de comunicare pipe cu nume, sub Windows.


ANEXA 3 Comunicarea între procese Windows prin memorie partajată

Fişiere I/O mapate în memorie şi zone partajate
Maparea (găzduirea) fişierelor în memoria internă este o facilitate preluată de Windows NT de la sistemul de operare DOS. Această mapare permite aplicaţiilor să acceseze părţi ale fişierului mapat folosin pointeri din memoria internă, în loc de accesare a discului. Prin aceasta se obţine o viteză de acces mult mai mare. Printre alte avantaje ale mapării, mai amintim faptul că se beneficiază de mecanismul de cache-ing şi de paginare a memoriei interne, oferit de Windows NT.

O aplicaţie poate mapa fişiere de la 1 octet până la 2G octeţi. Fişierele mapate în memorie permit, de asemnea, ca două sau mai multe procesoare să partajeze aceste fişiere şi implicit să partajeze memoria internă.

În continuare, prezentăm o succesiune de 5 (cinci) paşi ce trebuie urmaţi de orice aplicaţie Windows care foloseşte o zonă de memorie partajată:


  1. Crearea segmentului de memorie partajată folosind funcţia CreateFileMapping.

Această operaţie se poate realiza î două moduri:


    1. folosind un fişier definit anterior de către utilizator, cu ajutorul apelurilor CreateFile sau OpenFile.

    2. Folosind o pagină sistem, specificată cu ajutorul unui handler predefinit, cu valoarea 0xFFFFFFFF.

Dacă segmentul de memorie partajată există deja, deschiderea accesului la segment se obţine cu ajutorul funcţiei OpenFileMapping. Obiectul Windows, asociat segmentului de memorie partajată, poartă numele de file-mapping. Atât funcţia CreateFileMapping, cât şi funcţia OpenFileMapping întorc un handle la obiectul file-mapping asociat segmentului de memorie partajată referit.



  1. Maparea propriu-yisă a segmentului de memorie partajată (reprezentat prin

obiectul file-mapping), în spaţiul de memorie al procesului curent, este realizată cu ajutorul apelului MapViewOfFile. Această funcţie întoarce un pointer la o porţiune din această memorie partajată.

  1. Pointerul obţinut în urma apelului precedent, permite aplicaţiei apelante să

acceseze zona de memorie partajată în citire şi/sau scriere, în funcţie de parametrii specificaţi la apel.

  1. Operaţia complementară celei de mapare, se realizează cu ajutorul apelului UnmapViewOfFile. Astfel, se realizează ”detaşarea” aplicaţiei curente de la segmentul de memorie partajată, prin eliberarea spaţiului de memorie ocupat prin operaţia de mapare.

  2. În final, închiderea handle-ului la obiectul file-mapping se realizează cu funcţia CloseHandle. De asemenea, folosind CloseHandle, se închide fişierul deschis cu CreateFile sau OpenFile.

Crearea/deschiderea în varianta 1.b, cu handle-ul special 0xFFFFFFFF permite folosirea unei singure zone partajate în sistem. Folosind numai acest handle, NU este posibil ca pe acelaşi sistem să existe mai multe zone de memorie partajată. Pentru a permite ca fiecare grup de procese să-şi folosească propria zonă de memorie partajată, trebuie să se folosească crearea/deschiderea în varianta 1.a, CreateFile/OpenFile. Astfel, se creează/deschide câte un fişier mapat în memorie pentru fiecare zonă de memorie partajată dorită.

În continuare, punctăm o comparaţie, la nivel API, între operaţiile de lucru cu memorie partajată sub Unix şi sub Windows:
CreateFileMapping - -> shmget

MapViewOfFile - -> shmat

UnmapViewOfFile - -> shmdt

CloseHandle - -> shmctl


Sintaxa exactă a funcţiilor implicate în utilizarea segementelor de memorie partajată sub Windows, va fi descrisă mai jos.

Prototipurile funcţiilor CreateFile, ReadFile şi WriteFile au fost prezentate în 3.2.3.2.

Prototipurile celorlalte funcţii folosite sunt descrise în continuare:
HANDLE CreateFileMapping (

HANDLE hFis,

LPSECURITY_ATTRIBUTES descr_sec,

DWORD prot,

DWORD maxHigh,

DWORD maxLow,

LPCTSTR nume_file_mapping

) ;
unde:


hFis - Este handle la fişierul de mapat; valoarea 0xFFFFFFFF pentru acest

parametru indică o pagină implicit sistem.

descr_sec - Este descriptor de securitate; dacă se specifică valoarea NULL pentru

acest parametru, sistemul va folosi atributele de securitate implicite.

prot - Este atributul de protecţie pentru obiectul de mapat.

maxHigh şi maxLow - Compun dimensiunea pe 32 de biţi a obiectului de mapat. nume_file_mapping - Este numele obiectului file mapping

HANDLE OpenFileMapping (

DWORD acces,

BOOL bHandleMostenire,

LPCTSTR nume_file_mapping

) ;
unde:

acces - Indică modul de acces (citire şi/sau scriere).

bHandleMostenire - Indică dacă obiectul file-mapping va fi moştenit de

eventuale procese fii.

nume_file_mapping - Este numele obiectului file-mapping.
LPVOID MapViewOfFile (

HANDLE hFileMap,

DWORD acces,

DWORD offsetHigh,

DWORD offsetLow,

DWORD nrOctetiDeMapat

) ;
unde:

hFileMap – Este handle la obiectul file-mapping (handle returnat de

CreateFileMapping).

acces – Indică modul de acces (citire şi/sau scriere).


offsetHigh şi offsetLow - Compun offsetul pe 32 de biţi, a zonei de memorie de

mapat.


nrOctetiDeMapat – Este numărul de octeţi de mapat.

BOOL UnmapViewOfFile (LPCVOID lpAdresaMapata);


unde:

lpAdresaMapata – Este adresa de memorie unde începe maparea


Pentru mai multe informaţii legate de semnificaţia parametrilor şi prototipurilor funcţiilor ce operează cu memorie partajată sub Windows, se recomandă consultarea documentaţiei MSDN.
Implementarea foii de calcul sub Windows
Aplicaţia de mai jos implementează calculul tabelar pentru problema definită în 3.3.1. Programul 3.35 este fişierul header al aplicaţiei, similar Programului 3.31.
#include

#include

#include

#include

#include

#include

#include “semnaturaTemporala.cpp”

#define SMAX 1000

struct foaie_de_calcul {

char s[4] [100];

int v[4];

};

#define LUNFIME siyeof (struct foaie_de_calcul)



#define NUME_SEGMENT_MEMORIE_PARTAJATA “MemoriaMeaPartajata”
Programul 3.35. Fişierul header memPartFoaieWin.h
Fişierul header defineşte foaia de calcul, lungimea acesteia şi defineşte numele segmentului de memorie partajată.

La fel ca în cazul comunicării folosind pipe, şi mecanismul de comunicare folosind memorie partajată, sub Windows, presupune că creatorul obiectului file-mapping este activ, cât timp scriitorii şi cititorii partajează resursa respectivă. De aceea, vom include operaţia de creare a obiectului file-mapping în programul care accesează obiectul file-mapping în scriere.

Sursele programele scriitor şi cititor sunt prezentate în Programul 3.36, respectiv 3.37.
#include “memPartFoaieWin.h”

// 0


#define NR_ITER 100
int main ( ) {

int it, shmd, i, x,;

struct foaie_de_calcul *mp;

char s [SMAX];

HANDLE handleMemoriePartajata;

// creeaza obiectul file-mapping

handleMemoriePartajata =

CreateFileMapping (

(HANDLE) 0XFFFFFFFF, NULL,

PAGE_READWRITE, 0,

sizeof (struct foaie_de_calcul),

NUME_SEGMENT_MEMORIE_PARTAJATA);


assert (handleMemoriePartajata! = NULL);
mp = (struct foaie_de_clacul *)MapViewOfFile (

handleMemoriePartajata, FILE_MAP_WRITE, 0, 0, 100);

assert (mp! = NULL);
// 1

for (it = 0; it

i = rand ( ) % 3 ;

x = 1 + rand ( ) % 99;

strcpy (s, semanaturaTemporala ( ) );

// 2


strcpy (mp - >s [i], s);

mp -> v [3] = mp -> v [3] - mp ->v [i] + x;

mp -> v [i] = x;

strcpy (mp -> s[3], s);

//3

}

UnmapViewOfFile (mp);



CloseHandle (handleMemoriePartajat);

//4


}
Programul 3.36. Sursa memPartScriitorFoaie.cpp

#include “memPartFoaieWin.h”

#define NR_ITER 50
int main ( ) {
int it, shmd, i, x, j;

struct foaie_de_calcul *mp, *copie;

char s [SMAX];

HANDLE handleMemoriePartajata;


// deschide un obiect file-mapping

handleMemoriePartajata = OpenFileMapping (

FILE_MAP_READ, 0, NUME_SEGMENT_MEMORIE_PARTAJATA);
assert (handlerMemoriePartajata! = NULL);
mp = (struct foaie_de_calcul *)

MapViewOfFile (handleMemoriePartajata,

FILE_MAP_READ, 0, 0, 0);

assert (mp! = NULL);


copie = (struct foaie_de_calcul * ) malloc (sizeof (struct foaie_de_calcul ) );
for (it = 0; itfor (j=0;j<4; j++) {

copie -> v[j] = mp -> v [j];

strcpy (copie) -> s [j], mp -> s[j] );

}
strcpy (s, semanaturaTemporala ( ) );

x = copie -> v [3] – copie -> v [0] – copie -> v[1] – copie -> v[2];

i = o;
if (strcmp (copie -> s[3], copie -> s[0] ) && strcmp (copie -> s [3],

copie -> s[1]) && strcmp (copie -> s[3], copie -> s [2]) )

i = 1;

printf (“citire: %s”, s);



if (i) printf (“\tSemnatura total eronata!”);

if (x) printf (“\%d este diferenta la total!”, x);

printf (“\n”);
for (i=o; i<4; i++)

printf (“%s\t%d\n”, copie -> s [i], copie -> v [i] );

printf (“\n”);

}

UnmapViewOfFile (mp);



CloseHandle (handleMemoriePartajata);

}
Programul 3.37. Sursa memPartCititorFoaie.cpp








Yüklə 486,94 Kb.

Dostları ilə paylaş:
1   ...   19   20   21   22   23   24   25   26   27




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©muhaz.org 2022
rəhbərliyinə müraciət

    Ana səhifə