Programowanie współbieżne i rozproszone. Procesy współbieżne

Podobne dokumenty
Wielozadaniowość w systemie Microsoft Windows

Tworzenie i zarządzanie wątkami

Programowanie współbieżne. Tworzenie i obsługa semaforów oraz wątków przy użyciu funkcji Windows API.

Plan prezentacji: 1. Czym jest proces? 2. Czym jest wątek? 3. Funkcje do zarządzania wątkami w Win32API. 4. Mechanizmy synchronizacji wątków

Programowanie wielowątkowe. Jarosław Kuchta

Urządzenia peryferyjne RS-232 oprogramowanie pod WINDOWS. Wykład 3

Mechanizmy pracy równoległej. Jarosław Kuchta

Obserwacje kierunku rozwoju współczesnych

Aplikacja Sieciowa wątki po stronie klienta

Komunikacja między sterownikami przez protokół ADS

5. Model komunikujących się procesów, komunikaty

IPC: Kolejki komunikatów

Działanie systemu operacyjnego

Programowanie współbieżne Wykład 10 Synchronizacja dostępu do współdzielonych zasobów. Iwona Kochańska

Pliki. Funkcje tworzące pliki i operujące na nich opisane są w części 2 pomocy systemowej. Tworzenie i otwieranie plików:

4. Procesy pojęcia podstawowe

Działanie systemu operacyjnego

Kolejki FIFO (łącza nazwane)

Działanie systemu operacyjnego

TRX API opis funkcji interfejsu

Komunikacja za pomocą potoków. Tomasz Borzyszkowski

Procesy, wątki i zasoby

4. Procesy pojęcia podstawowe

Temat zajęć: Tworzenie i obsługa wątków.

Architektura komputerów

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Lekcja 10. Uprawnienia. Dołączanie plików przy pomocy funkcji include() Sprawdzanie, czy plik istnieje przy pmocy funkcji file_exists()

Biblioteka standardowa - operacje wejścia/wyjścia

Microsoft Visual C++

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Wprowadzenie do programowania współbieżnego

4. Procesy pojęcia podstawowe

Programowanie równoległe i rozproszone. Monitory i zmienne warunku. Krzysztof Banaś Programowanie równoległe i rozproszone 1

Programowanie współbieżne Wykład 7. Iwona Kochaoska

SYSTEMY CZASU RZECZYWISTEGO - VxWorks

Klient-Serwer Komunikacja przy pomocy gniazd

Poniższe funkcje opisane są w 2 i 3 części pomocy systemowej.

Działanie systemu operacyjnego

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Instrukcja do laboratorium Systemów Operacyjnych (semestr drugi)

Komunikaty w Windows. Jarosław Kuchta

Projektowanie oprogramowania systemów PROCESY I ZARZĄDZANIE PROCESAMI

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Laboratorium Systemów Operacyjnych. Ćwiczenie 4. Operacje na plikach

76.Struktura oprogramowania rozproszonego.

Dodatek B. Zasady komunikacji z otoczeniem w typowych systemach komputerowych

Mikroprocesor Operacje wejścia / wyjścia

Instrukcja programu użytkownika OmegaUW.Exe. Program obsługuje następujące drukarki fiskalne: ELZAB OMEGA II generacji ELZAB OMEGA F, MERA, MERA F.

INFORMATYKA Studia Niestacjonarne Elektrotechnika

Smarty PHP. Leksykon kieszonkowy

Pomoc dla użytkowników systemu asix 6 i 7. Drajwer Bufor. Dok. Nr PLP6021 Wersja:

Podstawy programowania komputerów

Zdalne wywołania procedur. Jarosław Kuchta Programowanie Współbieżne

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Wstęp do programowania 2

Pliki. Operacje na plikach w Pascalu

Wykład PASCAL - Pliki tekstowe

System plików. Warstwowy model systemu plików

Podręcznik programisty

Procesy i wątki. Krzysztof Banaś Obliczenia równoległe 1

Programowanie współbieżne i równoległe. dr inż. Marcin Wilczewski 2013

Funkcje zawarte w bibliotece < io.h >

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

Programowanie współbieżne i rozproszone

Tryby komunikacji między procesami w standardzie Message Passing Interface. Piotr Stasiak Krzysztof Materla

Współbieżność w środowisku Java

ZASADY PROGRAMOWANIA KOMPUTERÓW

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

SEGMENT TCP CZ. II. Suma kontrolna (ang. Checksum) liczona dla danych jak i nagłówka, weryfikowana po stronie odbiorczej

Podstawy programowania skrót z wykładów:

OPERACJE NA PLIKACH. Podstawowe pojęcia:

asix4 Podręcznik użytkownika CtSNPX - drajwer protokołu SNPX sterowników GE Fanuc Podręcznik użytkownika

Laboratorium z systemów operacyjnych. System plików - funkcje systemowe. Anna Wojak

Operacje wejścia/wyjścia (odsłona druga) - pliki

Wstęp System Windows ma wbudowany zestaw funkcji służących do komunikacji i współdzielenia danych między procesami. Ogólnie, operacje udostępniane prz

Jak Windows zarządza pamięcią?

Procesy, zasoby i wątki

Procesy, zasoby i wątki

Procesy, zasoby i wątki

4. Pliki Informacje ogólne o dostępie do plików w PHP Sprawdzanie istnienia pliku file_exists()

PhysX Visual Debugger. Tomasz Gańko

Programowanie w języku C++

Podstawy i języki programowania

System plików warstwa fizyczna

System plików warstwa fizyczna

System plików warstwa fizyczna

SYSTEMY OPERACYJNE: STRUKTURY I FUNKCJE (opracowano na podstawie skryptu PP: Królikowski Z., Sajkowski M. 1992: Użytkowanie systemu operacyjnego UNIX)

Kontrola sesji w PHP HTTP jest protokołem bezstanowym (ang. stateless) nie utrzymuje stanu między dwoma transakcjami. Kontrola sesji służy do

Funkcje zawarte w bibliotece < io.h >

Programowanie w językach

Mechanizmy z grupy IPC

Mariusz Rudnicki PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO CZ.4

Czym jest DLL Injection

Urządzenia wejścia-wyjścia

Kontrola topto. 1. Informacje ogólne. 2. Wymagania sprzętowe i programowe aplikacji. 3. Przykładowa instalacja topto. 4. Komunikacja.

Metody obsługi zdarzeń

Wykład 3. Procesy i wątki. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Systemy operacyjne III

SystimPlus. Dokumentacja (FAQ) dla wersji: v

Transkrypt:

Programowanie współbieżne i rozproszone Procesy współbieżne

Zawartość Procesy i wątki: Procesy współbieżne Synchroniczne i asynchroniczne operacje I/O Możliwości i ograniczenia; operacje I/O i potrzeba synchronizacji, Tworzenie aplikacji współbieżnych w systemie Windows Tworzenie potoku funkcja CreateNamedPipe, Nawiązywanie połączenia przez potok funkcje ConnectNamedPipe, DisconnectNamedPipe, CreateFile Operacje I/O funkcje WriteFile, ReadFile, PeekNamedPipe

Sekwencyjność a współbieżność Wykonanie sekwencyjne Poszczególne akcje procesu są wykonywane jedna po drugiej kolejna akcja rozpoczyna się po całkowitym zakończeniu poprzedniej. Wykonanie współbieżne Kolejna akcja rozpoczyna się przed zakończeniem poprzedniej. Akcje te są wykonywane równolegle lub w przeplocie.

Równoległość a współbieżność Wykonanie równoległe Kilka akcji jest wykonywanych w tym samym czasie. Jest to "prawdziwa" współbieżność, możliwa do uzyskania na komputerze z wieloma procesorami lub wielu komputerach. Wykonanie w przeplocie Jednocześnie odbywa się wykonanie tylko jednej akcji, jednak jest wiele czynności rozpoczętych i wykonywanych na zmianę krótkimi fragmentami. Wykonanie współbieżne jest abstrakcją równoległości i zawiera w sobie zarówno wykonania równoległe jak i wykonania w przeplocie

Wykonanie równoległe procesy czas Procesy wykonywane równolegle (tyle procesów, co procesorów/rdzeni)

Wykonanie w przeplocie wykonywanie czas gotowość/wstrzymanie Procesy wykonywane w przeplocie (mogą mieć różny priorytet na przydział czasu procesora)

Procesy współbiezne Środowisko wielozadaniowe (Unix, Linux, Windows XP/Vista) może współbieżnie wykonywać wiele procesów. Dopóki procesy te nie współzależą od siebie, każdy może być traktowany jak wykonywany sekwencyjnie.

Procesy współbieżne procesy czas Procesy wykonywane współbieżnie (a) Procesy niezależne od siebie

Procesy współbiezne Środowisko wielozadaniowe (Unix, Linux, Windows XP/Vista) może współbieżnie wykonywać wiele procesów. Dopóki procesy te nie współzależą od siebie, każdy może być traktowany jak wykonywany sekwencyjnie. Procesy współbieżne mogą wpływać na wykonanie innych procesów lub od nich w pewien sposób zależeć. Do zarządzania pracą procesów współbieżnych system operacyjny udostępnia szereg mechanizmów: Synchronizacja (Mutex, Semaphore, CriticalSection) Sygnalizacja (Event, Message) Komunikacja (Pipe, Shared Memory)

Procesy współbieżne procesy Sync I/O Req Sync I/O Compl Sync czas Procesy wykonywane współbieżnie (b) Procesy komunikują się ze sobą i są zależne od siebie nawzajem

Procesy współbiezne Komunikacja między procesami może odbywać się przy wykorzystaniu dwóch mechanizmów: Potok (ang. Pipe) rodzaj strumienia I/O, ustanawianego między procesami (zamiast, jak zwykle, między procesem a urządzeniem I/O); Potok łączy tylko dwa procesy i nie ma możliwości zmiany danych uprzednio do niego wpisanych Współdzielona pamięć (ang. Shared Memory) Obszar pamięci o dostępie swobodnym, współdzielony pomiędzy wieloma procesami; w praktyce plik wymiany Niezależnie od metody, komunikacja między procesami odbywa się według reguł operacji I/O i wymaga sprawnej sygnalizacji oraz synchronizacji.

Programy współbieżne Możliwości i ograniczenia: Odrębna przestrzeń adresowa wymiana danych między procesami: przez operacje I/O, przy współudziale systemu operacyjnego Wykonanie współbieżne (równoległe lub w przeplocie) konieczność synchronizacji, zwłaszcza operacji I/O

Operacje I/O Operacje I/O mogą być wykonywane w trzech różnych trybach: Synchronicznie z blokowaniem Proces zgłasza do systemu żądanie operacji I/O z własnej inicjatywy i zostaje wstrzymany aż do zakończenia operacji I/O Synchronicznie bez blokowania Proces zgłasza do systemu żądanie operacji I/O z własnej inicjatywy. Operacja I/O zostaje zakończona natychmiast, nawet jeżeli nie kończy się powodzeniem w takim przypadku proces musi sam zadbać o zgłoszenie żądania za jakiś czas. Asynchronicznie Proces zgłasza do systemu żądanie operacji I/O. Operacja I/O nie jest wykonywana natychmiast a proces nie jest wstrzymywany. Kiedy system zakończy operację I/O, poinformuje o tym proces, który zgłaszał żądanie, sposobem określonym przy zgłaszaniu żądania

Operacje I/O procesy OS I/O przekazanie sterowania czas Operacja I/O synchroniczna z blokowaniem: Wstrzymanie procesu do zakończenia operacji I/O.

Operacje I/O procesy OS I/O przekazanie sterowania czas Operacja I/O synchroniczna bez blokowania: Zakończenie operacji I/O, z powodzeniem lub bez.

Operacje I/O procesy OS I/O I/O Req I/O Compl przekazanie sterowania czas Operacja I/O asynchroniczna: System operacyjny powiadamia o zakończeniu I/O.

Programy wielowątkowe Zastosowanie: Bardziej efektywne wykorzystanie możliwości systemu systemy rastrowe, wieloprocesorowe i wielordzeniowe Wykonywanie niektórych czynności w czasie rzeczywistym tzw. systemy osadzone, obsługa multimediów itd. Zapobieganie blokowaniu głównego wątku w czasie operacji wejścia/wyjścia dysk, COM/LPT/USB, sieć itp. Zapobieganie blokowaniu wątku z GUI podczas czasochłonnych operacji kodowanie AV, nagrywanie CD/DVD itp. Wykonywanie mniej pilnych czynności w tle, kiedy główny wątek programu jest mniej obciążony - np. indeksowanie, drukowanie itp.

Program jednowątkowy procesy/wątki czas Proces jest wykonywany sekwencyjnie (może być równolegle z innymi procesami)

Program wielowątkowy procesy/wątki czas Proces jest podzielony na wątki, wykonywane współbieżnie (może być równolegle z innymi procesami)

Programy współbieżne/wielowątkowe procesy/wątki czas Wykonanie blokujących operacji I/O przez wydzielony wątek

Pipe Do obsługi potoków dedykowane są funkcje: CreateNamedPipe, CreatePipe WaitNamedPipe, ConnectNamedPipe, PeekNamedPipe, DisconnectNamedPipe Ponadto można wykorzystywać: WriteFile, ReadFile, WaitForSingleObject, WaitForMultipleObjects CloseHandle GetLastError

CreatePipe Funkcja CreatePipe tworzy anonimowy potok, który można wykorzystać w obrębie jednego procesu (wielowątkowego): BOOL CreatePipe( PHANDLE hreadpipe, PHANDLE hwritepipe, LPSECURITY_ATTRIBUTES lppipeattributes, DWORD nsize ); Argumenty: hreadpipe, hwritepipe wskaźniki do zmiennych, które otrzymają uchwyty do obu końców potoku (odczyt/zapis) lpthreadattributes wskaźnik do struktury atrybutów nsize rozmiar bufora (0 domyślny)

CreateNamedPipe Funkcja CreateNamedPipe tworzy nazwany potok, który można wykorzystać do komunikacji między procesami: HANDLE CreateNamedPipe( LPCTSTR lpname, DWORD dwopenmode, DWORD dwpipemode, DWORD nmaxinstances, DWORD noutbuffersize, DWORD ninbuffersize, DWORD ndefaulttimeout, LPSECURITY_ATTRIBUTES lpsecurityattributes ); Argumenty: lpname nazwa potoku, która musi mieć postać: \\.\pipe\nazwa

CreateNamedPipe Argumenty (c.d.): dwopenmode tryb dostępu do potoku - PIPE_ACCESS_DUPLEX zapis i odczyt, - PIPE_ACCESS_INBOUND od klienta do serwera, - PIPE_ACCESS_OUTBOUND od serwera do klienta, oraz dodatkowe flagi: - FILE_FLAG_WRITE_THROUGH bez buforowania; istotne tylko przy komunikacji przez sieć, - FILE_FLAG_OVERLAPPED tryb overlapped (asynchroniczny)

CreateNamedPipe Argumenty (c.d.): dwpipemode tryb pracy potoku, sposób zapisu: - PIPE_TYPE_BYTE zapis do potoku binarny - PIPE_TYPE_MESSAGE zapis tekstowy (tylko w trybie overlapped!) sposób odczytu: - PIPE_READMODE_BYTE odczyt z potoku binarny - PIPE_READMODE_MESSAGE odczyt tekstowy (tylko przy zapisie tekstowym!) oraz blokowanie I/O: - PIPE_WAIT potok blokujący - PIPE_NOWAIT potok nieblokujący (kompatybilność wstecz, niezalecane)

CreateNamedPipe Argumenty (c.d.): nmaxinstances maksymalna liczba instancji potoku (komunikacja serwer wiele klientów) noutbuffersize wielkość bufora wyjściowego (tylko sugestia, ustala system operacyjny) ninbuffersize wielkość bufora wyjściowego (uwagi jw.) ndefaulttimeout domyślny czas oczekiwania na połączenie z potokiem dla funkcji WaitNamedPipe lpsecurityattributes wskaźnik do struktury atrybutów bezp.

CreateNamedPipe Przykład uzycia: HANDLE Pipe; Pipe = CreateNamedPipe ( "\\\\.\\pipe\\testpipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE PIPE_WAIT, 1, 2048, 2048, 1000, NULL ); if (Pipe==INVALID_HANDLE_VALUE) //obsługa błędu Funkcja CreateNamedPipe tworzy nazwany potok i zwraca uchwyt do niego albo, w przypadku niepowodzenia, stałą INVALID_HANDLE_VALUE. Aby skorzystać z potoku, trzeba następnie użyć ConnectNamedPipe.

ConnectNamedPipe Funkcja ConnectNamedPipe czeka aż proces klienta połączy się z potokiem utworzonym wcześniej przez funkcję CreateNamedPipe: BOOL ConnectNamedPipe( HANDLE hnamedpipe, LPOVERLAPPED lpoverlapped ); Argumenty: hnamedpipe uchwyt potoku, lpoverlapped wskaźnik struktury Overlapped, używanej przy operacjach I/O asynchronicznych; wymagany dla potoku z flagą FILE_FLAG_OVERLAPPED, dozwolony dla pozostałych

ConnectNamedPipe Przykład uzycia: BOOL Res; Res = ConnectNamedPipe (Pipe, NULL); if (!Res) //obsługa błędu Jeżeli wskaźnik struktury Overlapped nie zostanie podany, funkcja działa synchronicznie, tj. powoduje wstrzymanie procesu aż do połączenia z klientem. Jeżeli potok został utworzony z flagą FILE_FLAG_OVERLAPPED, wskaźnik do struktury Overlapped jest wymagany, zaś sruktura ta musi zawierać uchwyt obiektu Event resetowanego ręcznie.

DisconnectNamedPipe Funkcja DisconnectNamedPipe rozłącza serwerowy koniec nazwanego potoku: BOOL DisconnectNamedPipe( HANDLE hnamedpipe, ); Argumenty: hnamedpipe uchwyt potoku, Jeżeli potok zawiera jeszcze jakiekolwiek nie odczytane dane, zostaną one utracone.

DisconnectNamedPipe Przykład uzycia: BOOL Res; Res = DisconnectNamedPipe(Pipe); if (!Res) //obsługa błędu Jeżeli potok od strony klienta jest otwarty, zostanie wymuszone jego zamknięcie. Klient nie jest o tym informowany, za to następna operacja I/O zakończy się błędem. Klient musi i tak sam zamknąć swój koniec potoku funkcją CloseHandle. Po zamknięciu potoku z obu końców, serwer może użyć potoku do połączenia z następnym klientem.

CreateFile Funkcja CreateFile otwiera strumień I/O, którym może być m.in. plik, konsola lub nazwany potok: HANDLE CreateFile( LPCTSTR lpfilename, DWORD dwdesiredaccess, DWORD dwsharemode, LPSECURITY_ATTRIBUTES lpsecurityattributes, DWORD dwcreationdistribution, DWORD dwflagsandattributes, HANDLE htemplatefile ); Argumenty: lpname nazwa strumienia, która musi mieć postać: \\.\pipe\nazwa; potok musi być wcześniej utworzony funkcją CreateNamedPipe.

CreateFile Argumenty (c.d.): dwdesiredaccess żądany tryb dostępu: GENERIC_READ możliwość odczytu danych, GENERIC_WRITE możliwość zapisu danych; Aby uzyskać prawo odczytu i zapisu, należy podać obie flagi. dwsharemode określa sposób współdzielenia dostępu: FILE_SHARE_DELETE równoczesne kasowanie FILE_SHARE_READ równoczesny odczyt FILE_SHARE_WRITE równoczesny zapis; Jeżeli podana będzie wartość 0, to równoczesne operacje są zabronione, zaś funkcja CreateFile kolejnego procesu spowoduje jego wstrzymanie aż do zamknięcia uchwytu przez pierwszy proces

CreateFile Argumenty (c.d.): lpsecurityattributes wskaźnik do struktury atrybutów bezp. dwcreationdistribution określa sposób traktowania zasobu, zależnie od tego czy już istnieje, czy nie: - CREATE_NEW tworzy nowy zasób (niepowodzenie, jeżeli istnieje) - CREATE_ALWAYS jeżeli istnieje to usuwa, następnie tworzy nowy, - OPEN_EXISTING otwiera istniejący (niepowodzenie, jeżeli nie istnieje) - OPEN_ALWAYS - jeżeli nie istnieje to tworzy, następnie otwiera,

CreateFile Argumenty (c.d.): dwflagsandattributes atrybuty pliku, tj. dowolna kombinacja atrybutów: - FILE_ATTRIBUTE_ARCHIVE, - FILE_ATTRIBUTE_HIDDEN, - FILE_ATTRIBUTE_READONLY, - FILE_ATTRIBUTE_SYSTEM, albo FILE_ATTRIBUTE_NORMAL (brak atrybutów); można też dodać flagi określajace sposób pracy, m.in.: - FILE_FLAG_DELETE_ON_CLOSE, - FILE_FLAG_RANDOM_ACCESS, - FILE_FLAG_SEQUENTIAL_SCAN; - FILE_FLAG_OVERLAPPED tryb overlapped (asynchroniczny); za wyjątkiem FILE_FLAG_OVERLAPPED bez znaczenia dla potoku

CreateFile Argumenty (c.d.): htemplatefile uchwyt do szablonu pliku, z dostępem GENERIC_READ, z którego skopiowane zostaną wszystkie flagi i atrybuty tworzonego pliku (albo NULL). Ważne jest, aby atrybuty przekazane funkcji CreateFile po stronie klienta były zgodne z podanymi dla funkcji CreateNamedPipe po stronie serwera inaczej potoku nie uda się utworzyć.

CreateFile Przykład uzycia: HANDLE Pipe; Pipe = CreateFile ( "\\\\.\\pipe\\testpipe", GENERIC_READ GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (Pipe==INVALID_HANDLE_VALUE) //obsługa błędu Funkcja CreateFile otwiera nazwany potok od strony klienta i zwraca uchwyt do niego albo, w przypadku niepowodzenia, stałą INVALID_HANDLE_VALUE. Serwer musi wcześniej utworzyć potok (CreateNamedPipe) i czekać na połączenie klienta (ConnectNamedPipe).

WriteFile Funkcja WriteFile zapisuje dane do strumienia I/O, którym może być m.in. plik, konsola lub potok: BOOL WriteFile( HANDLE hfile, LPCVOID lpbuffer, DWORD nnumberofbytestowrite, LPDWORD lpnumberofbyteswritten, LPOVERLAPPED lpoverlapped ); Argumenty: hfile uchwyt strumienia I/O, który musi być otwarty oraz mieć dostęp GENERIC_WRITE

WriteFile Argumenty (c.d.): lpbuffer wskaźnik do bufora zawierającego dane do zapisu, nnumberofbytestowrite liczba bajtów do zapisania, lpnumberofbyteswritten wskaźnik do zmiennej, gdzie zostanie wpisana liczba bajtów faktycznie zapisanych; Może być NULL, jeżeli lpoverlapped jest NULL lpoverlapped wskaźnik struktury Overlapped, używanej przy operacjach I/O asynchronicznych; wymagany dla potoku z flagą FILE_FLAG_OVERLAPPED, dozwolony dla pozostałych

WriteFile Przykład uzycia: BOOL res; DWORD len; DWORD knd = 1; CHAR msg[] = "Message"; len = strlen (msg) + 1; WriteFile (Pipe, &knd, sizeof(knd), NULL, NULL); WriteFile (Pipe, &len, sizeof(len), NULL, NULL); res = WriteFile (Pipe, msg, len, NULL, NULL); if (!res) //obsługa błędu Funkcja WriteFile zapisuje dane binarnie, dlatego najbezpieczniej jest stosować metodę TLV (Type-Length-Value). W przypadku potoku, serwer musi wcześniej utworzyć potok (CreateNamedPipe) i zaczekać na połączenie klienta (ConnectNamedPipe), zaś klient połączyć się (CreateFile).

ReadFile Funkcja ReadFile odczytuje dane ze strumienia I/O, którym może być m.in. plik, konsola lub potok: BOOL ReadFile( HANDLE hfile, LPCVOID lpbuffer, DWORD nnumberofbytestoread, LPDWORD lpnumberofbytesread, LPOVERLAPPED lpoverlapped ); Argumenty: hfile uchwyt strumienia I/O, który musi być otwarty oraz mieć dostęp GENERIC_READ

ReadFile Argumenty (c.d.): lpbuffer wskaźnik do bufora na dane do odczytania, nnumberofbytestoread liczba bajtów do odczytania, lpnumberofbytesread wskaźnik do zmiennej, gdzie zostanie wpisana liczba bajtów faktycznie odczytanych; Może być NULL, jeżeli lpoverlapped jest NULL lpoverlapped wskaźnik struktury Overlapped, używanej przy operacjach I/O asynchronicznych; wymagany dla potoku z flagą FILE_FLAG_OVERLAPPED, dozwolony dla pozostałych Jeżeli wskaźnik struktury Overlapped nie zostanie podany, funkcja działa synchronicznie, tj. powoduje wstrzymanie procesu aż do wpisania danych do potoku przez drugi proces.

ReadFile Przykład uzycia: BOOL res; DWORD knd=0, len=0; CHAR msg[100]; ReadFile (Pipe, &knd, sizeof(knd), NULL, NULL); ReadFile (Pipe, &len, sizeof(len), NULL, NULL); if (knd==1 && len>0) { res = ReadFile (Pipe, msg, len, NULL, NULL); if (!res) //obsługa błędu } Funkcja ReadFile odczytuje dane binarnie. Sposób odczytu musi być zgodny ze sposobem zapisu. Najbezpieczniej jest stosować metodę TLV.

PeekNamedPipe Funkcja PeekNamedPipe kopiuje dane z potoku (jednak bez usuwania ich z potoku) oraz dostarcza informacji o stanie potoku: BOOL PeekNamedPipe( HANDLE hnamedpipe, LPVOID lpbuffer, DWORD nbuffersize, LPDWORD lpbytesread, LPDWORD lptotalbytesavail, LPDWORD lpbytesleftthismessage ); Argumenty: hnamedpipe uchwyt potoku (dostarczony przez funkcję CreateNamedPipe lub CreateFile), który musi być otwarty oraz mieć dostęp GENERIC_READ

PeekNamedPipe Argumenty (c.d.): lpbuffer wskaźnik do bufora na dane do odczytania; może być NULL, jeżeli dane nie mają być odczytane, nbuffersize liczba bajtów do odczytania, lpbytesread wskaźnik do zmiennej, gdzie zostanie wpisana liczba bajtów faktycznie odczytanych; może być NULL lptotalbytesavail liczba bajtów dostępnych do odczytania, lpbytesleftthismessage dla trybu PIPE_TYPE_MESSAGE, liczba bajtów bieżącej wiadomości, które nie zmieściły się w buforze Funkcja PeekNamedPipe nie wstrzymuje procesu (jak ReadFile) i nie usuwa odczytanych danych z bufora potoku. Jeżeli parametr nbuffersize ma wartość 0, to funkcja jedynie sprawdza stan potoku, niczego nie odczytując.

PeekNamedPipe Przykład uzycia: BOOL res; DWORD len=0; CHAR msg[100]; PeekNamedPipe (Pipe, NULL, 0, NULL, &len, NULL); if (len>0) { res = ReadFile (Pipe, msg, len, NULL, NULL); if (!res) //obsługa błędu } Funkcja PeekNamedPipe może być wykorzystana do nieblokujących operacji odczytu danych z potoku (zamiast używania flagi PIPE_NOWAIT). Kiedy stosowana jest metoda TLV, funkcja PeekNamedPipe może służyć do odczytania początkowej partii danych, aby określić ich typ oraz rozmiar (aby np. przygotować bufor odpowiedniej wielkości), a także aby sprawdzić, czy kompletne dane są już dostępne do odczytu.

WaitNamedPipe Funkcja WaitNamedPipe wstrzymuje proces, aż potok o wskazanej nazwie będzie dostępny lub do upłynięcia limitu czasu: BOOL WaitNamedPipe( LPCTSTR lpnamedpipename, DWORD ntimeout ); Argumenty: lpname nazwa potoku, która musi mieć postać: \\.\pipe\nazwa ntimeout limit czasu oczekiwania, w milisekundach; można też użyć jednej ze stałych: - NMPWAIT_USE_DEFAULT_WAIT wartość domyślna (podana w funkcji CreateNamedPipe), - NMPWAIT_WAIT_FOREVER do skutku

WaitNamedPipe Przykład uzycia: BOOL res; HANDLE Pipe; res = WaitNamedPipe ( "\\\\.\\pipe\\testpipe", 0); if (res) Pipe = CreateFile (... Funkcja WaitNamedPipe zwraca wartość niezerową jeżeli potok jest dostępny (serwer czeka na połączenie ConnectNamedPipe) lub 0 w przeciwnym wypadku. Potok jest niedostępny, jeżeli nie został utworzony (CreateNamedPipe) albo jest już zajęty. Funkcja ta nie daje pełnej wiedzy o sytuacji (jeżeli potok nie jest dostępny, to nie jest wiadome z jakiego powodu), nie zapewnia też synchronizacji (pozytywny rezultat WaitNamedPipe nie gwarantuje udanego połączenia przy użyciu CreateFile).

OVERLAPPED Struktura OVERLAPPED, potrzebna do asynchronicznych operacji I/O: typedef struct _OVERLAPPED { DWORD Internal; DWORD InternalHigh; DWORD Offset; DWORD OffsetHigh; HANDLE hevent; } OVERLAPPED; Elementy składowe: Internal, InternalHigh zarezerwowane dla OS; nie wolno zmieniać Offset, OffsetHigh pozycja w pliku (w bajtach), począwszy od której ma być wykonana operacja I/O; w przypadku potoków musi być 0, hevent uchwyt zdarzenia (obiektu Event), który zostanie ustawiony w stan sygnalizowany, kiedy tylko operacja I/O zostanie zakończona

OVERLAPPED Przykład uzycia: OVERLAPPED ovr; memset (&ovr, "\0", sizeof(ovr)); ovr.hevent = hovr; ConnectNamedPipe (Pipe, &ovr); // gdzieś indziej: res = WaitForSingleObject (hovr, 0) if (res==wait_object_0) // dzlsze działania Operacje asynchroniczne są intensywnie promowane przez MS. W rzeczywistości są przydatne dopiero wtedy, gdy operacje I/O są licznie i intensywnie wykonywane przez program, np. jeżeli proces serwera obsługuje wiele procesów klientów równocześnie.

OVERLAPPED Asynchroniczne wykonywanie operacji I/O otwiera wiele nowych możliwości, m.in. możliwość obsługi wielu operacji I/O, różnego typu (konsola, pliki, potoki, porty szeregowe i równoległe, sieć komputerowa) równocześnie. Wykonanie asynchroniczne operacji I/O powoduje znaczne skomplikowanie programu np. ze względu na możliwość zakończenia się takiej operacji podczas kiedy proces jest wstrzymany (funkcje WaitFor). Z tego względu pojawiły się rozszerzone wersje wielu funkcji API, m.in.: WaitForSingleObjectEx, WaitForMultipleObjectEx, ReadFileEx, WriteFileEx, SleepEx

Thread Do obsługi wątków dedykowane są funkcje: CreateThread ResumeThread i SuspendThread TerminateThread ExitThread i GetExitCodeThread Ponadto można wykorzystywać: WaitForSingleObject, WaitForMultipleObjects CloseHandle GetLastError

CreateThread Funkcja CreateThread tworzy wątek uruchamiany we wspólnej przestrzeni adresowej z procesem macierzystym: HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpthreadattributes, DWORD dwstacksize, LPTHREAD_START_ROUTINE lpstartaddress, LPVOID lpparameter, DWORD dwcreationflags, LPDWORD lpthreadid ); Argumenty: lpthreadattributes wskaźnik do struktury atrybutów dwstacksize rozmiar stosu (0 jak dla macieżystego procesu)

CreateThread Argumenty (c.d.): lpstartaddress adres funkcji wątku, która typowo ma postać: DWORD WINAPI ThreadFunc(LPVOID lpparameter) { // wykonanie zadania wątku, // z parametrami dostępnymi przez lpparam } return 0; lpparameter adres przez który można przekazać parametry wątku dwcreationflags czy wątek ma od razu wystartować (0), czy czekać na uruchomienie (CREATE_SUSPENDED) lpthreadid adres, pod którym zostanie zapisany identyfikator wątku

CreateThread Przykład uzycia: HANDLE Thr; DWORD ThrID; Thr = CreateThread (NULL, 0, ThreadFunction, &Param, 0, &ThrID); if (Thr==NULL) //obsługa błędu Funkcja ThreadFunction zostanie wykonana jako odrębny wątek. Wykonywanie wątku rozpocznie się natychmiast. Uchwyt (Thr) oraz identyfikator (ThrID) mogą być użyte do zarządzania wątkiem np. uchwyt w ResumeThread, SuspendThread, TerminateThread

ResumeThread Funkcja ResumeThread zmniejsza tzw. licznik zawieszenia wątku. Kiedy licznik osiągnie zero, wykonanie wątku zostaje wznowione: DWORD ResumeThread( HANDLE hthread ); Argumenty: hthread uchwyt wątku Jako rezultat funkcja zwraca poprzednią (sprzed jej wywołania) wartość licznika zawieszenia wątku

ResumeThread Przykład uzycia: HANDLE Thr; DWORD ThrID; Thr = CreateThread (NULL, 0, ThrFoo, NULL, CREATE_SUSPENDED, &ThrID); //gdzieś dalej: ResumeThread (Thr); Wątek utworzony z argumentem dwcreationflags równym CREATE_SUSPENDED nie jest wykonywany (od momentu utworzenia jest zawieszony). Wykonywanie wątku rozpocznie się dopiero po wywołaniu ResumeThread.

SuspendThread Funkcja SuspendThread zawiesza wykonanie wątku i zwiększa licznik zawieszenia wątku: DWORD ResumeThread( HANDLE hthread ); Argumenty: hthread uchwyt wątku Jako rezultat funkcja zwraca poprzednią (sprzed jej wywołania) wartość licznika zawieszenia wątku

SuspendThread Przykład uzycia: HANDLE Thr; Thr = CreateThread (NULL, 0, ThrFoo, NULL, 0, NULL); SuspendThread (Thr); // i gdzieś dalej ResumeThread (Thr); Wątek może być dowolnie zawieszany i wznawiany. Ze względu na licznik zawieszenia, aby doszło do wznowienia wątku, funkcja ResumeThread musi być wywołana tyle samo razy, co wcześniej funkcja SuspendThread (można też sprawdzić i wykorzystać rezultat dostarczany przez funkcję ResumeThread).

ExitThread Funkcja ExitThread kończy wykonywanie wątku: VOID ExitThread( DWORD dwexitcode ); Argumenty: dwexitcode kod wyjścia; może być sprawdzany przez macierzysty proces funkcją GetExitCodeThread W głównej funkcji wątku zamiast ExitThread wystarczy instrukcja return (ExitThread jest wówczas wykonywana niejawnie). Po wykonaniu funkcji ExitThread uchwyt wątku zmienia stan na sygnalizowany, co może być wykryte przez funkcje WaitFor.

ExitThread Przykład uzycia: DWORD WINAPI ThreadFunc (LPVOID lpparameter) { Foo (lpparameter); return 0; } VOID Foo (LPVOID lpparameter) { if (warunek) ExitThread (1); } Zwykle wartość kodu wyjścia 0 oznacza normalne zakończenie, inne wartości sygnalizują błąd wykonania (np. jeżeli wątek nie wykonał swojego zadania). Wartości kodu wyjścia ma znaczenie tylko dla macierzystego procesu system nie bierze go pod uwagę

GetExitCodeThread Funkcja ExitThread kończy wykonywanie wątku: BOOL GetExitCodeThread( HANDLE hthread, LPDWORD lpexitcode ); Argumenty: hthread uchwyt wątku lpexitcode adres, pod który funkcja wpisze kod wyjścia; Jeżeli wykonanie funkcji zakończy się powodzeniem (warunkiem jest aby hthread był uchwytem do wątku, który już zakończył działanie), funkcja zwraca TRUE, a pod wskazany adres wpisuje kod wyjścia wątku. W przeciwnym wypadku funkcja zwraca wartość 0, a szczegóły można uzyskać funkcją GetLastError

GetExitCodeThread Przykład uzycia: HANDLE Thr; DWORD Ext; Thr = CreateThread (NULL, 0, ThrFoo, NULL, 0, NULL); // i gdzieś dalej if (GetExitCodeThread(Thr, &Ext)) // wątek zakończony, kod wyjścia: Ext Zwykle wartość kodu wyjścia 0 oznacza normalne zakończenie, inne wartości sygnalizują błąd wykonania (np. jeżeli wątek nie wykonał swojego zadania).

TerminateThread Funkcja TerminateThread wymusza zakończenie wykonywania wątku: BOOL TerminateThread( HANDLE hthread, DWORD dwexitcode ); Argumenty: hthread uchwyt wątku, który ma być zakończony dwexitcode kod wyjścia; może być sprawdzany funkcją GetExitCodeThread Funkja TerminateThread wymusza zakończenie wątku, nie dając mu (wątkowi) szansy na jakiekolwiek działania kończące (np. zamknięcie otwartych plików, połączeń sieciowych itp.) powinna być używana tylko w wyjątkowych sytuacjach.

ExitThread, WaitForSingleObject Przykład uzycia: HANDLE Thr, Trm; Trm = CreateEvent (NULL, FALSE, FALSE, NULL); Thr = CreateThread (NULL, 0, ThrFoo, NULL, 0, NULL); // i gdzieś dalej SetEvent (Trm); WaitForSingleObject (Thr, INFINITE); // wątek zakończony Znacznie lepiej jest zasygnalizować wątkowi, że powinien kończyć działalność, np. ustawiając dedykowane do tego zdarzenie (Event) w stan sygnalizowany. Oczywiście wątek musi okresowo sprawdzać stan zdarzenia.

RegisterWindowMessage Funkcja RegisterWindowMessage definiuje komunikat systemowy, którego identyfikator jest unikalny: UINT RegisterWindowMessage( LPCTSTR lpstring ); Argumenty: lpstring adres łańcucha znaków identyfikującego komunikat Funkcja dostarcza jako rezultat identyfikator komunikatu (jest to liczba z zakresu 0xC000 do 0xFFFF).

RegisterWindowMessage Przykład uzycia: UINT msgdone; msgdone = RegisterWindowMessage ("Zrobione!"); Dzięki unikalności identyfikatora, komunikat może służyć do sygnalizacji zarówno pomiędzy wątkami jednego procesu, jak i pomiędzy procesami. Jednak aby można było odbierać komunikaty, proces (wątek) musi obsługiwać kolejkę komunikatów. Aplikacje z GUI taką kolejkę mają i obsługują.

PostMessage Funkcja PostMessage wysyła komunikat systemowy: BOOL PostMessage( HWND hwnd, UINT Msg, WPARAM wparam, LPARAM lparam ); Argumenty: hwnd uchwyt okna, do którego wysyłany jest komunikat Msg identyfikator komunikatu (predefiniowany systemu Windows lub uzyskany przez funkcję RegisterWindowMessage) wparam, lparam dodatkowe parametry, które mogą być wykorzystane podczas obsługi komunikatu; znaczenie zależne od komunikatu

SendMessage Funkcja SendMessage wysyła komunikat systemowy i czeka na jego obsłużenie: BOOL SendMessage( HWND hwnd, UINT Msg, WPARAM wparam, LPARAM lparam ); Argumenty: hwnd uchwyt okna, do którego wysyłany jest komunikat Msg identyfikator komunikatu (predefiniowany systemu Windows lub uzyskany przez funkcję RegisterWindowMessage) wparam, lparam dodatkowe parametry jak w PostMessage

PostMessage Przykład uzycia: UINT msgdone; msgdone = RegisterWindowMessage ("Zrobione!"); HANDLE Wnd = Form->Handle; // gdzieś w wątku: PostMessage (Wnd, msgdone, 0, 0); Funkcja umieszcza komunikat w kolejce komunikatów systemowych i natychmiast wraca nie czeka na obsłużenie komunikatu. W Builderze komunikaty takie można przechwytywać w funkcji obsługi zdarzenia OnMessage obiektu ApplicationEvents.

OnMessage Przykład uzycia:... AppMessage(tagMSG &Msg, bool &Handled) { if (Msg.message == msgdone) { // obsługa Handled = true; } } Należy być bardzo ostrożnym przy tworzeniu funkcji obsługi tego zdarzenia błąd może zawiesić całą aplikację. Przez OnMessage przechodzą wszystkie zdarzenia systemowe.

OnMessage Przykład uzycia:... AppMessage(tagMSG &Msg, bool &Handled) { if (Msg.message == msgdone) { // obsługa Handled = true; } } Należy być bardzo ostrożnym przy tworzeniu funkcji obsługi tego zdarzenia błąd może zawiesić całą aplikację. Przez OnMessage przechodzą wszystkie zdarzenia systemowe.

OnMessage Struktura komunikatu jest zdefiniowna jako: typedef struct tagmsg { HWND hwnd; UINT message; WPARAM wparam; LPARAM lparam; DWORD time; POINT pt; } MSG; Pole message jest identyfikatorem komunikatu, pola wparam i lparam (typu DWORD, tj. unsigned long int) pochodzą z wywołania PostMessage i SendMessage.

CriticalSection Do obsługi sekcji krytycznej dedykowane są funkcje: InitializeCriticalSection, EnterCriticalSection, TryEnterCriticalSection LeaveCriticalSection, DeleteCriticalSection, Obiekt CriticalSection łączy w sobie funkcjonalność Muteksu i funkcji WaitFor

InitializeCriticalSection Funkcja InitializeCriticalSection inicjuje obiekt sekcji krytycznej: VOID InitializeCriticalSection( LPCRITICAL_SECTION lpcriticalsection ); Argumenty: lpcriticalsection wskaźnik do struktury typu CRITICAL_SECTION

InitializeCriticalSection Przykład uzycia: CRITICAL_SECTION Sct; InitializeCriticalSection (&Sct); Zwykle główny wątek programu tworzy (poprzez zadeklarowanie) i przy pomocy InitializeCriticalSection inicjuje sekcję krytyczną. Z obiektu tego mogą następnie korzystać wszystkie wątki współdzielące zasoby.

EnterCriticalSection Funkcja EnterCriticalSection czeka na uzyskanie wyłącznego dostępu do sekcji krytycznej: VOID EnterCriticalSection( LPCRITICAL_SECTION lpcriticalsection ); Argumenty: lpcriticalsection wskaźnik do struktury typu CRITICAL_SECTION

LeaveCriticalSection Funkcja EnterCriticalSection powoduje zrzeczenie się wyłącznego dostępu do sekcji krytycznej: VOID LeaveCriticalSection( LPCRITICAL_SECTION lpcriticalsection ); Argumenty: lpcriticalsection wskaźnik do struktury typu CRITICAL_SECTION

EnterCriticalSection, LeaveCriticalSection Przykład uzycia: CRITICAL_SECTION Sct; InitializeCriticalSection (&Sct); // gdzieś dalej EnterCriticalSection (&Sct); // sekcja krytyczna LeaveCriticalSection (&Sct); Funkcja powoduje zawieszenie procesu (wątku) aż do uzyskania wyłącznego dostępu do sekcji krytycznej. Po wykonaniu funkcji, wątek staje się właścicielem sekcji krytycznej i może swobodnie korzystać ze współdzielonych zasobów.

TryEnterCriticalSection Funkcja TryEnterCriticalSection czeka na uzyskanie wyłącznego dostępu do sekcji krytycznej: BOOL TryEnterCriticalSection( LPCRITICAL_SECTION lpcriticalsection ); Argumenty: lpcriticalsection wskaźnik do struktury typu CRITICAL_SECTION

TryEnterCriticalSection Przykład uzycia: if (TryEnterCriticalSection (&Sct)) { // sekcja krytyczna LeaveCriticalSection (&Sct); } Funkcja nie powoduje zawieszenie procesu (wątku). Funkcja sprawdza, czy jest możliwe uzyskanie wyłącznego dostępu do sekcji krytycznej. Jeżeli tak, to funkcja zwraca TRUE, a wątek staje się właścicielem sekcji krytycznej i może swobodnie korzystać ze współdzielonych zasobów. W przeciwnym razie zwraca FALSE. Używanie TryEnterCriticalSection zamiast EnterCriticalSection może powodować problemy z żywotnością -

DeleteCriticalSection Funkcja DeleteCriticalSection zwalnia wszystkie zasoby używane przez sekcję krytyczną: BOOL DeleteCriticalSection ( LPCRITICAL_SECTION lpcriticalsection ); Argumenty: lpcriticalsection wskaźnik do struktury typu CRITICAL_SECTION

DeleteCriticalSection Przykład uzycia: CRITICAL_SECTION Sct; InitializeCriticalSection (&Sct); // gdzieś dalej EnterCriticalSection (&Sct); // sekcja krytyczna LeaveCriticalSection (&Sct); // na koniec DeleteCriticalSection (&Sct); Nie jest to obowiązkowe (zasoby zostaną i tak zwolnione po zakończeniu programu), jednak zalecane, ponieważ odciąża system.

Mutex Do obsługi muteksów dedykowane są funkcje: CreateMutex OpenMutex ReleaseMutex Ponadto można wykorzystywać: WaitForSingleObject, WaitForMultipleObjects CloseHandle GetLastError

CreateMutex Funkcja CreateMutex tworzy nazwany lub nienazwany muteks i zwraca uchwyt do niego: HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpmutexattributes, BOOL binitialowner, LPCTSTR lpname ); Argumenty: lpmutexattributes wskaźnik do struktury atrybutów binitialowner flaga okreslająca, czy proces tworzący ma być początkowo w posiadaniu muteksu lpname nazwa muteksu

CreateMutex Przykład uzycia: HANDLE Mux; Mux = CreateMutex (NULL, FALSE, NULL); if (Mux==NULL) //obsługa błędu Muteks bez nazwy (jako trzeci argument należy podać NULL) może być użyty tylko przez jeden proces (nie ma możliwości przekazania uchwytu do innego procesu) przydaje się w aplikacjach wielowątkowych. Ze względu na brak nazwy, nie można uzyskać uchwytu do muteksu przy pomocy funkcji OpenMutex

WaitForSingleObject Funkcja WaitForSingleObject czeka na ustawienie obiektu w stan sygnalizowania: DWORD WaitForSingleObject( HANDLE hhandle, DWORD dwmilliseconds ); Argumenty: hhandle uchwyt obiektu, na który funkcja czeka dwmilliseconds czas oczekiwania w milisekundach może być 0 (funkcja de facto nie czeka, a sprawdza), wartość niezerowa lub stała INFINITE (do skutku)

WaitForSingleObject Zwracane wartości: WAIT_ABANDONED muteks nie został zwolniony, lecz proces, który go posiadał został zakończony (co może oznaczać błąd wykonania sekcji krytycznej) WAIT_OBJECT_0 wystąpiło oczekiwane zdarzenie WAIT_TIMEOUT upłynął limit czasu dwmilliseconds i nic się nie stało Funkcja WaitForSingleObject zmienia stan też obiektu np. muteks zostanie ustawiony w stan zajętości zasobu proces staje się jego wyłącznym właścicielem i może wejść do sekcji krytycznej.

ReleaseMutex Funkcja ReleaseMutex zwalnia muteks: BOOL ReleaseMutex( HANDLE hmutex ); Argumenty: hmutex uchwyt zwalnianego muteksu Proces przestaje być właścicielem muteksu, co pozwala przejąć muteks przez inny proces. Zwolnienie muteksu powinno nastąpić natychmiast po wyjściu z sekcji krytycznej.

WaitForSingleObject, ReleaseMutex Przykład uzycia: HANDLE Mux; Mux = CreateMutex (NULL, FALSE, "Nazwa"); while (1) { WaitForSingleObject (Mux, INFINITE); // sekcja krytyczna ReleaseMutex (Mux); if (warunek) break; }

WaitForMultipleObjects Funkcja WaitForMultipleObjects czeka na ustawienie jednego lub wszystkich obiektu w stan sygnalizowania: DWORD WaitForMultipleObjects( DWORD ncount, CONST HANDLE *lphandles, BOOL bwaitall, DWORD dwmilliseconds ); Argumenty: ncount liczba obiektów w tablicy lphandles lphandles wskaźnik tablicy z uchwytami obiektów bwaitall flaga określająca, czy czekać na wszystkie obiekty, czy na którykolwiek z nich dwmilliseconds czas oczekiwania (0 INFINITE)

WaitForMultipleObjects Zwracane wartości: WAIT_ABANDONED_0 pierwszy w tablicy muteks nie został zwolniony, lecz proces, który go posiadał został zakończony WAIT_ABANDONED_0 + n jw., dla n-tego muteksu WAIT_OBJECT_0 wystąpiło pierwsze oczekiwane zdarzenie WAIT_OBJECT_0 + n jw., dla n-tego obiektu WAIT_TIMEOUT upłynął limit czasu dwmilliseconds i nic się nie stało Funkcja WaitForMultipleObjects zmienia stan też obiektu, analogicznie jak funkcja WaitForSingleObject.

WaitForMultipleObjects Przykład uzycia: HANDLE MuxTab[2]; // utworzenie wszystkich muteksów while (1) { Res = WaitForMultipleObjects(2, MuxTab, FALSE, INFINITE); } if (Res== WAIT_OBJECT_0) { // sekcja krytyczna 0 ReleaseMutex (MuxTab[0]); if (warunek) break; } if (Res== WAIT_OBJECT_0 + 1) { // sekcja krytyczna 1 ReleaseMutex (MuxTab[1]); if (warunek) break; }

CloseHandle Funkcja CloseHandle zamyka obiekt inedtyfikowany przez uchwyt: BOOL CloseHandle( HANDLE hobject ); Argumenty: hobject uchwyt zamykanego obiektu Obiekt nie zostanie zniszczony, dopóki korzystają z niego inne procesy. Dopiero po zamknięciu uchwytu przez ostatni z nich, obiekt jest niszczony. Jawne zamykanie uchwytów nie jest niezbędne system zamyka wszystkie uchwyty w chwili zakończenia procesu jednak zalecane, kiedy obiekt jest niepotrzebny odciąża to system.

Event Do obsługi zdarzeń dedykowane są funkcje: CreateEvent OpenEvent SetEvent, PulseEvent ResetEvent Ponadto można wykorzystywać: WaitForSingleObject, WaitForMultipleObjects CloseHandle GetLastError

CreateEvent Funkcja Create Event tworzy nazwane lub nienazwane zdarzenie i zwraca uchwyt do niego: HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpmutexattributes, BOOL bmanualreset, BOOL binitialstate, LPCTSTR lpname ); Argumenty: lpmutexattributes wskaźnik do struktury atrybutów bmanualreset czy zdarzenie ma być resetowane przez ResetEvent, czy przez system (w rezultacie funkcji WaitForSingle/MultipleObject) binitialstate czy w momencie utworzenia zdarzenie ustawione lpname nazwa zdarzenia

CreateEvent Przykład uzycia: HANDLE Ev; Ev = CreateEvent(NULL, FALSE, FALSE, "Nazwa"); if (Ev==NULL) //obsługa błędu Zdarzenie bez nazwy (podobnie jak Muteks) może być użyte tylko przez jeden proces przydaję się w aplikacjach wielowątkowych. Zdarzenie nazwane może być użytkowane przez różne procesy. Kolejne procesy mogą uzyskać uchwyt do zdarzenia (o ile tylko znają jego nazwę) przy pomocy funkcji OpenEvent

OpenEvent Funkcja OpenEvent zwraca uchwyt istniejącego zdarzenia: HANDLE OpenEvent( DWORD dwdesiredaccess, BOOL binherithandle, LPCTSTR lpname ); Argumenty: dwdesiredaccess EVENT_ALL_ACCESS lub EVENT_MODIFY_STATE binherithandle czy uchwyt może być dziedziczony lpname nazwa zdarzenia

OpenEvent Przykład uzycia: HANDLE Ev; Ev = OpenEvent(EVENT_ALL_ACCESS, FALSE, "Nazwa"); if (Ev==NULL) //obsługa błędu Funkcja zakończy się niepowodzeniem, jeżeli zdarzenie nie istnieje (lub nazwa nie zostanie podana). Szczegóły można uzyskać funkcją GetLastError

SetEvent Funkcja SetEvent ustawia zdarzenie w stan sygnalizowany: BOOL SetEvent( HANDLE hevent ); Argumenty: hevent uchwyt zdarzenia, które ma być ustawione Ustawienie zdarzenia w stan sygnalizowany jest wykrywane przez funkcje WaitForSingle/MultipleObject. Wszystkie procesy czekajace na zdarzenie zostaną wznowione.

PulseEvent Funkcja PulseEvent ustawia zdarzenie w stan sygnalizowany, a następnie przestawia je w stan nie sygnalizowany: BOOL PulseEvent( HANDLE hevent ); Argumenty: hevent uchwyt zdarzenia, które ma być ustawione Ustawienie zdarzenia w stan sygnalizowany jest wykrywane przez funkcje WaitForSingle/MultipleObject. Jeżeli zdarzenie jest resetowane automatycznie, tylko jeden oczekujący proces zostanie wznowiony; jeżeli resetowanie jest ręczne wszystkie procesy.

ResetEvent Funkcja ResetEvent resetuje zdarzenie (przestawia zdarzenie w stan nie sygnalizowany): BOOL ResetEvent( HANDLE hevent ); Argumenty: hevent uchwyt zdarzenia, które ma być ustawione Zdarzenie jest resetowane przez WaitForSingle/MultipleObject, o ile argument bmanualreset funkcji CreateEvent był równy FALSE. W przeciwnym wypadku zdarzenie jest w stanie sygnalizowanym aż do wykonania ResetEvent.

CreateEvent, SetEvent Przykład uzycia: HANDLE Ev; Ev = CreateEvent(NULL, FALSE, FALSE, "Nazwa"); // gdzieś dalej: if (warunek) { SetEvent (Ev); }

OpenEvent, WaitForSingleObject Przykład uzycia: HANDLE Ev; Ev = OpenEvent(EVENT_ALL_ACCESS, FALSE, "Nazwa"); while (1) { if (WaitForSingleObject (Ev, 0)== WAIT_OBJECT_0) // reakcja na zdarzenie if (warunek) break; }