[header.htm]
Process Synchronization Comparison
Shared memory allows fast communications between two processes on same machine
This returns a HANDLE to the mapped file
This returns a pointer to the view of the mapped file.
used for two processes to share memory
This returns a HANDLE to the mapped file
(source code here for producer)
//*************************************************************** // illustrates two processes cooperating in a producer/consumer relationship // This code demonstrates the parent side of handle inheritance. // The producer/consumer relationship is managed by two semaphores // EMPTY and FULL, When EMPTY the producer can produce into empty buffer, // when FULL the consumer can consume buffer. // Buffers are passed through shared memory implemented as a memory mapped file // AUTHOR: Chris Wild // DATE: September 10, 1997 //*************************************************************** #include <windows.h> #include <iostream.h> #include <stdlib.h> const int NBUFFERS = 3; // allow 3 buffers for bounded buffer typedef struct{ int bufID; int bufValue; } Buffer; void main(void) { HANDLE empty, full; HANDLE mapFileHandle; Buffer* commonBuffers; // Create the semaphores empty = CreateSemaphore(0,NBUFFERS,NBUFFERS, "NTcourse.semaphore.empty"); full = CreateSemaphore(0,0,NBUFFERS, "NTcourse.semaphore.full"); cout << "created semaphores\n"; // create in-memory file for Interprocess Communications mapFileHandle = CreateFileMapping( (HANDLE) 0xFFFFFFFF, // unnamed file maps to virtual memory 0, // security PAGE_READWRITE, // access to file 0, // high word of file size NBUFFERS*sizeof(Buffer), // size of memory mapped area "commonBuffer"); // name it to share with other processes commonBuffers = (Buffer*) MapViewOfFile(mapFileHandle, FILE_MAP_WRITE, 0, // High offset 0, // Low offest 0); // 0 for mapping entire file // enter a loops producing some things int bufN = 0; for(int i = 0; i < 10; i++) { // First wait for previous resource to be empty (consumed) cout << "PRODUCER: waiting for empty buffer\n"; WaitForSingleObject(empty, INFINITE); commonBuffers[bufN].bufID = bufN; commonBuffers[bufN].bufValue = 1000*i; bufN = (bufN+1) % NBUFFERS; // Have empty resource - use it to produce // put code here to produce something cout << "PRODUCER: producing a new buffer\n"; ReleaseSemaphore(full,1,0); // signals production } CloseHandle(empty); CloseHandle(full); CloseHandle(mapFileHandle); }
(source code here for consumer)
//... HANDLE empty, full; // control bounded buffer access HANDLE mapFileHandle; // used to access the shared Buffer* commonBuffers; // pointer into memory mapped file to array of buffer structures cout << "Entered consumer: v2\n"; empty = OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE, "NTcourse.semaphore.empty"); if(empty == NULL) { cout << "Error opening empty: " << GetLastError() << endl; ExitProcess(1); } full = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, "NTcourse.semaphore.full"); if(full == NULL) { cout << "Error opening full: " << GetLastError() << endl; ExitProcess(1); } mapFileHandle = OpenFileMapping(PAGE_READWRITE, FALSE, // child cannot inherit "commonBuffer"); if(mapFileHandle == NULL) { cout << "Error opening commonBuffer: " << GetLastError() << endl; ExitProcess(1); } commonBuffers = (Buffer*) MapViewOfFile(mapFileHandle, FILE_MAP_READ, 0, // High offset 0, // Low offest 0); // 0 for mapping entire file if(commonBuffers == NULL) { cout << "Error mapping file: " << GetLastError() << endl; ExitProcess(1); } // enter a loops consuming some things int bufN = 0; DWORD returnValue; while(true) { // First wait for buffer to be produced cout << "CONSUMER: waiting for full buffer\n"; returnValue = WaitForSingleObject(full, 10000); // wait 10 seconds if( returnValue == WAIT_TIMEOUT) { cout << "Waited too long for producer - assumed died\n"; break; } // Have full buffer - consume it cout << "CONSUMER: emptied buffer: " << commonBuffers[bufN].bufID << " with value: " << commonBuffers[bufN].bufValue << endl; bufN = (bufN+1) % NBUFFERS; ReleaseSemaphore(empty,1,0); // signals empty } CloseHandle(empty); CloseHandle(full); CloseHandle(mapFileHandle); }
(source code here for create process producer)
//... STARTUPINFO startUpInfo; PROCESS_INFORMATION procInfo; BOOL success; char s[100]; // command line arguments (unused in this example) // . . . GetStartupInfo(&startUpInfo); // short cut to fill most of the windowing parameters for child environment // Create the child process success=CreateProcess("consumer.exe", s, 0, 0, FALSE, CREATE_NEW_CONSOLE, 0, 0, &startUpInfo, &procInfo); if (!success) cout << "Error creating process v2: " << GetLastError() << endl; // . . . WaitForSingleObject(procInfo.hProcess, INFINITE); //. . .
[footer.htm]