Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > [WinAPI] управление памятью и обмен данными


Автор: anatox91 12.10.2010, 13:26
всем привет
у меня в лабе стоит такая задача:
Код

3.1.    Написать программу MemShare, выполняющую следующие действия:
3.1.1.    Создание(запуск) процесса MemSort(действия, выполняемые этим процессом описаны в п. 3.2), используя вызов CreateProcess;
3.1.2.    Выделение с помощью вызова VirtualAlloc заданного по варианту задания количество страниц памяти(страница 4096 байт);
3.1.3.    Заполнение выделенной памяти случайными числами в диапазоне от 0 до MAX(значение MAX выбирается исходя из типа данных, заданному по варианту задания);
3.1.4.    Перевод режима доступа выделенной памяти в ReadOnly(с помощью вызова VirtualProtect);
3.1.5.    Используя механизм отобра¬жения файлов на память (функции CreateFileMapping и MapViewOfFile) создание памяти общего доступа, с размером соответствующим размеру выделенной с помощью  VirtualAlloc памяти (задать имя создаваемого объекта отображения "memshare");
3.1.6.    Копирование данных из памяти выделенной с помощью  VirtualAlloc в память общего доступа (например, с помощью вызова CopyMemory);
3.1.7.    Ожидание процесса MemSort (используя заданный по варианту задания тип синхронизации необходимо ожидать пока процесс MemSort не подготовит данные);
3.1.8.    Перевод режима доступа выделенной в п. 3.1.1 памяти в ReadWrite(с помощью вызова VirtualProtect);
3.1.9.    Копирование данных из памяти общего доступа в память, выделеную с помощью VirtualAlloc (например, с помощью вызова CopyMemory);
3.1.10.    Вывод на экран данных из памяти, выделенной с помощью  VirtualAlloc;
3.1.11.    Освобождение выделенной памяти (с помощью вызова VirtualFree);
3.1.12.    Освободить память общего доступа (используя вызовы UnmapViewOfFile и СloseHandle);

3.2.    Написать программу MemSort выполняющую следующие действия:
3.2.1. Ожидание пока процесс MemShare не подготовит данные в памяти общего доступа (использовать заданный по варианту задания тип объекта синхронизации)
3.2.2. Открытие памяти общего доступа "memshare"(используя вызовы OpenFileMapping и MapViewOfFile);
3.2.3. Сортировка данных в памяти общего доступа, методом указанным в варианте задания.

я вот набросал кое-что:
Код

#include "stdafx.h"

#define memory_size (3*pageSize)

using std::cout;
using std::endl;

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE mutex = CreateMutex(NULL, FALSE, L"memsharemutex");
    //mutex = OpenMutex(SYNCHRONIZE, FALSE, L"memsharemutex");

    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    DWORD pageSize = sysInfo.dwPageSize;

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    if(!CreateProcess(
        NULL,
        L"lab5_memsort.exe",
        NULL,
        NULL,
        FALSE,
        NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
        NULL,
        NULL,
        &si,
        &pi
        )) {
            cout << "Can't create memsort process!" << endl;
            return 1;
    }

    short int *virtual_alloc_memory = (short int*)VirtualAlloc(NULL, memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    for(int i=0; i<memory_size/sizeof(short int); ++i) {
        virtual_alloc_memory[i] = rand()%SHRT_MAX;
    }

    DWORD old_protection;
    VirtualProtect(virtual_alloc_memory, memory_size, PAGE_READONLY, &old_protection);

    HANDLE mapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, memory_size, L"memshare");
    short int *shared_memory = (short int*)MapViewOfFile(mapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);

    CopyMemory(shared_memory, virtual_alloc_memory, memory_size);

    ReleaseMutex(mutex);
    WaitForSingleObject(mutex, INFINITE);

    VirtualProtect(virtual_alloc_memory, memory_size, PAGE_READWRITE, &old_protection);

    CopyMemory(virtual_alloc_memory, shared_memory, memory_size);

    cout << "Array of short int from the virtual allocated memory:" << endl;
    for(int i=0; i<memory_size/sizeof(short int); ++i) {
        cout << virtual_alloc_memory[i] << " ";
    }

    VirtualFree(virtual_alloc_memory, 0, MEM_RELEASE);
    UnmapViewOfFile(shared_memory);
    CloseHandle(mapFile);
    ReleaseMutex(mutex);
    CloseHandle(mutex);

    system("pause");

    return 0;
}

но программа вылетает то ли после создания процесса, то ли после первого выделения памяти... что тут не так?

Автор: GremlinProg 12.10.2010, 13:44
видимо, надо захватить мьютекс, чтобы lab5_memsort.exe не успел это сделать первым (если он конечно это делает):
Цитата

CreateMutex(NULL, TRUE, L"memsharemutex");

Автор: anatox91 12.10.2010, 13:48
ээ спасибо, я как раз не мог понять для чего этот параметр)) но проблему вылета это не решило, вылетает где-то в районе вызова CreateProcess()

Автор: GremlinProg 12.10.2010, 13:55
перед CreateProcess можно еще вставить GetStartupInfo( &si );
да и вообще, не хорошо передавать туда пустую структуру, там же указатели есть

Автор: anatox91 12.10.2010, 13:57
да это вряд ли из-за этого, в другой программе у меня этот же участок кода нормально срабатывал, процессы создавались на ура
бывают проблемы разве что если передать NULL вместо этих структур, а так нормально)

Автор: GremlinProg 12.10.2010, 14:10
если процесс создается, значит надо смотреть что он делает

Автор: anatox91 12.10.2010, 14:12
lab5_memsort.exe
Код

#include "stdafx.h"

#define memory_size (3*pageSize)

using std::cout;
using std::endl;

int _tmain(int argc, _TCHAR* argv[])
{
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    DWORD pageSize = sysInfo.dwPageSize;

    HANDLE mutex = OpenMutex(SYNCHRONIZE, FALSE, L"memsharemutex");
    WaitForSingleObject(mutex, INFINITE);

    HANDLE mapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"memshare");
    short int* shared_memory = (short int*)MapViewOfFile(mapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); 
    int n = memory_size/sizeof(short int);
    //sorting
    int max, tmp;
    for(int k=0; k<n-1; ++k) {
        max = k;
        for(int l=k+1; l<n; ++l) {
            if(shared_memory[max] < shared_memory[l]) max = l;
        }
        tmp = shared_memory[k];
        shared_memory[k] = shared_memory[max];
        shared_memory[max] = tmp;
    }

    //UnmapViewOfFile(shared_memory);
    ReleaseMutex(mutex);

    return 0;
}

Автор: GremlinProg 12.10.2010, 14:38
SYNCHRONIZE тут недостаточно, лучше MUTEX_ALL_ACCESS, но это не суть,
+ надо еще проверить mapFile и shared_memory

а вообще, поставь перед и после WaitForSingleObject MessageBox'ы:
если процесс создается, то ему ломаться просто негде до WaitForSingleObject

Автор: anatox91 12.10.2010, 16:24
сделал так:
lab5_memshare:
Код

MessageBox(NULL, L"123", L"123", MB_OK);
    if(!CreateProcess(
        NULL,
        L"lab5_memsort.exe",
        NULL,
        NULL,
        FALSE,
        NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
        NULL,
        NULL,
        &si,
        &pi
        )) {
            cout << "Can't create memsort process!" << endl;
            return 1;
    }
    MessageBox(NULL, L"456", L"456", MB_OK);

lab5_memsort:
Код

HANDLE mutex = OpenMutex(SYNCHRONIZE, FALSE, L"memsharemutex");
    MessageBox(NULL, L"123", L"123", MB_OK);
    WaitForSingleObject(mutex, INFINITE);
    MessageBox(NULL, L"456", L"456", MB_OK);


выводит только один раз 123 и вылетает, то есть именно при создании процесса и видимо до Wait'а...
сейчас еще попробую поэкспериментировать...

Добавлено @ 16:39
вобщем вылетает именно на вызове CreateProcess(), процесс не создается, GetStartupInfo() тоже не помог...

Автор: GremlinProg 12.10.2010, 21:11
Код

TCHAR szMemSort[] = TEXT("lab5_memsort.exe");
CreateProcess(
        NULL,
        szMemSort,
        ...
)

Автор: anatox91 13.10.2010, 15:59
помогло))) только я так и не понял в чем был прикол, ведь это тоже самое:
Код

#define TEXT(quote) __TEXT(quote)

Код

#define __TEXT(quote) L##quote

Автор: anatox91 13.10.2010, 16:18
но тут появилась еще одна проблемка: первый процесс(memshare) не ожидает пока второй отсортирует данные в памяти общего доступа и начинает их сразу выводить и в конце вылетает, т.е. синхронизация не работает, и я не могу понять что там не так... Если вот в этом участке кода после освобождения мьютекса добавить Sleep() на пару секунд, то второй процесс успевает отсортировать и все срабатывает нормально, но как это организовать с помощью мьютексов?
Код

CopyMemory(shared_memory, virtual_alloc_memory, memory_size);

ReleaseMutex(mutex);
//Sleep(5000);
WaitForSingleObject(mutex, INFINITE);

VirtualProtect(virtual_alloc_memory, memory_size, PAGE_READWRITE, &old_protection);


Добавлено через 2 минуты и 36 секунд
нужно просто сделать чтобы первый процесс выполнил необходимые операции с памятью, потом подождал пока другой процесс эти данные отсортирует, и вывел их

Добавлено через 3 минуты и 56 секунд
а второй процесс должен ждать пока первый выделит память, потом отсортировать ее и все

Автор: GremlinProg 13.10.2010, 17:00
Цитата(anatox91 @  13.10.2010,  17:59 Найти цитируемый пост)
ведь это тоже самое

дело не в TEXT, а в том, что в CreateProcess передавалась константа в качестве командной строки
(у нас уже был такой случай, можно было поискать)
Цитата(anatox91 @  13.10.2010,  18:18 Найти цитируемый пост)
как это организовать с помощью мьютексов?

завести второй мьютекс

Автор: anatox91 13.10.2010, 18:00
вот чуть подправил программки для двух мьютексов, но почему-то не срабатывает WaitForSingleObject() для второго мьютекса в первой программе, всегда вылетает окошко с ошибкой:
memshare
Код

#include "stdafx.h"

#define memory_size (3*pageSize)

using std::cout;
using std::endl;

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE mutex1 = CreateMutex(NULL, TRUE, L"memsharemutex1");

    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    DWORD pageSize = sysInfo.dwPageSize;

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    TCHAR szMemSort[] = TEXT("lab5_memsort.exe");
    if(!CreateProcess(
        NULL,
        szMemSort,
        NULL,
        NULL,
        FALSE,
        NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
        NULL,
        NULL,
        &si,
        &pi
        )) {
            cout << "Can't create memsort process!" << endl;
            return 1;
    }
    short int *virtual_alloc_memory = (short int*)VirtualAlloc(NULL, memory_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    for(int i=0; i<memory_size/sizeof(short int); ++i) {
        virtual_alloc_memory[i] = rand()%SHRT_MAX;
    }

    DWORD old_protection;
    VirtualProtect(virtual_alloc_memory, memory_size, PAGE_READONLY, &old_protection);

    HANDLE mapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, memory_size, L"memshare");
    short int *shared_memory = (short int*)MapViewOfFile(mapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);

    CopyMemory(shared_memory, virtual_alloc_memory, memory_size);

    ReleaseMutex(mutex1);
    HANDLE mutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, L"memsharemutex2");
    if(WaitForSingleObject(mutex2, INFINITE) != STATUS_WAIT_0) 
        MessageBox(NULL, L"error!", L"error!", MB_OK);

    VirtualProtect(virtual_alloc_memory, memory_size, PAGE_READWRITE, &old_protection);

    CopyMemory(virtual_alloc_memory, shared_memory, memory_size);

    cout << "Array of short int from the virtual allocated memory:" << endl;
    for(int i=0; i<memory_size/sizeof(short int); ++i) {
        cout << virtual_alloc_memory[i] << " ";
        //if(((i % 300) == 0) && (i > 1)) getchar();
    }

    cout << endl;

    VirtualFree(virtual_alloc_memory, 0, MEM_RELEASE);
    UnmapViewOfFile(shared_memory);
    CloseHandle(mapFile);
    ReleaseMutex(mutex2);
    CloseHandle(mutex1);
    CloseHandle(mutex2);

    system("pause");

    return 0;
}


в этом месте
Код

if(WaitForSingleObject(mutex2, INFINITE) != STATUS_WAIT_0) 
        MessageBox(NULL, L"error!", L"error!", MB_OK);

memsort
Код

#include "stdafx.h"

#define memory_size (3*pageSize)

using std::cout;
using std::endl;

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE mutex2 = CreateMutex(NULL, FALSE, L"memsharemutex2");

    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    DWORD pageSize = sysInfo.dwPageSize;

    HANDLE mutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, L"memsharemutex1");
    WaitForSingleObject(mutex1, INFINITE);

    HANDLE mapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"memshare");
    short int* shared_memory = (short int*)MapViewOfFile(mapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); 
    int n = memory_size/sizeof(short int);
    //sorting
    int max, tmp;
    for(int k=0; k<n-1; ++k) {
        max = k;
        for(int l=k+1; l<n; ++l) {
            if(shared_memory[max] < shared_memory[l]) max = l;
        }
        tmp = shared_memory[k];
        shared_memory[k] = shared_memory[max];
        shared_memory[max] = tmp;
    }

    //UnmapViewOfFile(shared_memory);

    ReleaseMutex(mutex1);
    ReleaseMutex(mutex2);

    return 0;
}

где я еще туплю?)

Автор: GremlinProg 13.10.2010, 18:38
нет гарантии, что на 52 строке memsort прошел 10, т.е. на 52 строке второй мьютекс может быть вообще еще не создан

самое простое: создать оба мьютекса в главной программе, она же по любому стартует первой
+ при открытии, надо захватить второй мьютекс в memsort, чтобы не было бесконечного Wait в 53 строке

Добавлено через 8 минут и 58 секунд
хотя, нет, это же мьютекс,
в 53 строке он может быть только захвачен раньше, чем в memsort,

значит это должен быть не мьютекс, а например событие, которое будет создаваться несигнальным, а сигнализироваться в memsort

Добавлено через 11 минут и 20 секунд
если это будет событие, то в memsort его нужно только открыть и заменить ReleaseMutex(mutex2) на SetEvent(mutex2)

ну, mutex2 можно конечно переименовать, оно теперь event smile

Автор: anatox91 13.10.2010, 20:02
не, в задании сказано только через мьютексы сделать синхронизацию

Добавлено через 1 минуту и 34 секунды
блин, можно ведь гораздо проще сделать, просто ожидать окончания процесса)))

Добавлено через 1 минуту и 56 секунд
и обойтись одним мьютексом)

Автор: GremlinProg 13.10.2010, 20:09
Цитата(anatox91 @  13.10.2010,  22:02 Найти цитируемый пост)
блин, можно ведь гораздо проще сделать, просто ожидать окончания процесса)))

 smile только в таком случае, мьютексы вообще не нужны  smile

Автор: anatox91 13.10.2010, 20:10
все отлично работает, спасибо еще раз)

Добавлено через 32 секунды
мьютекс нужен чтобы второй процесс подождал пока первый приготовит память

Автор: GremlinProg 13.10.2010, 20:20
Цитата(anatox91 @  12.10.2010,  15:26 Найти цитируемый пост)
Ожидание процесса MemSort (используя заданный по варианту задания тип синхронизации необходимо ожидать пока процесс MemSort не подготовит данные)

ожидать освобождения мьютекса, захваченного в MemSort можно только при наличии гарантии того, что этот мьютекс будет захвачен не memshare, а сделать это может только MemSort

т.е. если поменять местами программы, то такого эффекта можно добиться,
т.е. не MemSort запускать из memshare, а наоборот  smile 

либо можно использовать дополнительную синхронизацию событием для захвата мьютекса

Автор: anatox91 13.10.2010, 20:48
там в вариантах заданий кроме мьютексов были еще бинарные и считающие семафоры(у меня попался мьютекс), с помощью них это можно было бы сделать без ожидания окончания процесса и без событий? если нет, то это наверно ошибка в задании...

Автор: GremlinProg 13.10.2010, 21:35
без дополнительных синхронизаций, по-моему не реально (нельзя захватить мьютекс чужими руками, только своими),
а вот с одним барьером можно:
Код

memshare:
  m = CreateMutex( ..., FALSE, ... );
  e = CreateEvent( ..., TRUE, FALSE, ... );
  CreateProcess( ... );
  WaitForSingleObject( e, INFINITE );
  WaitForSingleObject( m, INFINITE );
  ...
memsort:
  m = OpenMutex( ... );
  e = OpenEvent( ... );
  WaitForSingleObject( m, INFINITE );
  SetEvent( e );
  сортировка
  ReleaseMutex( m );
  ...

тогда m будет решать поставленную задачу

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)