Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Mutex 
:(
    Опции темы
<Spawn>
Дата 20.10.2003, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



Так как данные моей ДЛЛ-ки будут использоваться разными процессами, то пришлось сделать функции синхронизации:
Код
procedure LockData; stdcall; export;
begin
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 //Дождаться перехода мьютекса в сигнальное состояние
 WaitForSingleObject(hMutex, INFINITE);
end;

procedure UnLockData; stdcall; export;
begin
 //Получить хендл мьютекса
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 ReleaseMutex(hMutex);
 CloseHandle(hMutex);
end;


Вроде все нормально, но появился странный глюк - при получении данных из блока памяти (FileMapping), второй элемент массива содержит бредовые значения(В нутри тела функции это значение равно установленному, при получении же его программой оно искажается).

Код
function GetShareData(Index:integer): integer; stdcall; export;
begin
Result:=0;
if Assigned(ShareData) then
 if IsValidIndex(Index) then
 begin
   Result:=GetInt(Index)^;
 end;
end;


Причем, если убрать эти функции при получении данных, то все нормально. Но без синхронизации ни как нельзя. Может есть другой способ ее сделать?

Это сообщение отредактировал(а) <Spawn> - 20.10.2003, 21:05


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
Dmitry V.Abramov
Дата 21.10.2003, 01:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 30.9.2003
Где: Saint-Petersburg

Репутация: 5
Всего: 4



Цитата

Код
procedure LockData; stdcall; export;
begin
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 //Дождаться перехода мьютекса в сигнальное состояние
 WaitForSingleObject(hMutex, INFINITE);
end;



Создали хендл для именованного мутеха. Зашли, заблокировав остальных. Вышли из процедуры.

Код
procedure UnLockData; stdcall; export;
begin
 //Получить хендл мьютекса
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 ReleaseMutex(hMutex);
 CloseHandle(hMutex);
end;


Создали хендл для именованного мутеха. Этим хэндлом затерли предыдищий, еще не закрытый...

Или что-то еще не оговорено?

Это сообщение отредактировал(а) Dmitry V.Abramov - 21.10.2003, 01:01
--------------------
/DVA
PM MAIL WWW   Вверх
<Spawn>
Дата 21.10.2003, 04:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



При вызове CreateMutex с именем уже существующего, возвращается хендл существующего мьютекса. По крайней мере, в одной книженции использован подобный подход из чего я сделал такой вывод.

Это сообщение отредактировал(а) <Spawn> - 21.10.2003, 04:19


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
stab
Дата 21.10.2003, 07:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 14
Всего: 48



Я так понимаю, что твоя прога ждет данных от dll загруженных в других процессах? Требуется: как-то информировать прогу о том, что данные поступили и на время обработки данных запретить модификацию другим процессам?


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
<Spawn>
Дата 21.10.2003, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



cully Совершенно верно. В ДЛЛ-ке реализованы различные функции для манипуляции данными, предоставленними CreateFileMapping+MapViewOfFile. Так как блок данных довольно большой и считывается блоками размером с integer то нужно делать блокировку на время получения данных. Вот как щас, но при этом совершенно мне непонятный глюк во втором элементе массива:

Код
try
 LockData;
 vCount:=GetValuesCount;
 for i:=0 to vCount-1 do
 begin
   addr.S_addr:=GetShareData(i);
   lbSharedIPList.Items.Add(inet_ntoa(addr));
 end;
finally
 UnLockData;
end;



--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
Dmitry V.Abramov
Дата 21.10.2003, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 30.9.2003
Где: Saint-Petersburg

Репутация: 5
Всего: 4



Цитата
При вызове CreateMutex с именем уже существующего, возвращается хендл существующего мьютекса. По крайней мере, в одной книженции использован подобный подход из чего я сделал такой вывод.

В win32 такого не бывает. Если тебе дали handle - изволь отдать, когда станет не нужен. Система ведет счетчик и по последнему СloseHandle уничтожит его физически. По "книжке" же тогда получается, что возможно уничтожить handle чужого процесса.

В принципе, пару хэндлов можно и позабыть - они высвободятся при завершении приложения. Но у тебя, насколько я понял, идут интенсивные обращения к LockData и свободные хэндлы вполне могут закончиться. Тогда не откроется очередной мутех - а на handle=0 ты не проверяешь. Вполне возможный сценарий...

Вот и Win32.hlp говорит:
Use the CloseHandle function to close the handle. The system closes the handle automatically when the process terminates. The mutex object is destroyed when its last handle has been closed.
--------------------
/DVA
PM MAIL WWW   Вверх
Dmitry V.Abramov
Дата 21.10.2003, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 30.9.2003
Где: Saint-Petersburg

Репутация: 5
Всего: 4



Цитата
При вызове CreateMutex с именем уже существующего, возвращается хендл существующего мьютекса.

Текст, действительно, двояко толкуется. Правильней звучало бы:

При вызове CreateMuytex система возвращает хэндл для одноименного мутеха если он уже существует, или создает новый...
--------------------
/DVA
PM MAIL WWW   Вверх
<Spawn>
Дата 22.10.2003, 05:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



Dmitry V.Abramov Все окей с мьютексами. Можно было бы обойтись и без CreateMutex, но в ДЛЛ-ке, используемая мною переменная hMutex, содержащая хендл мьютекса, равна 0 при обращении к UnLockData. Я кстати не раз встречал уже подобный случай в ДЛЛ. Может кто обьяснит мне из за чего происходит инициализация переменных заново? Но не в этом дело то, а втом что при их использовании появляются совсем неясные глюки со вторым элементом массива.

Это сообщение отредактировал(а) <Spawn> - 22.10.2003, 05:23


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
Dmitry V.Abramov
Дата 22.10.2003, 06:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 30.9.2003
Где: Saint-Petersburg

Репутация: 5
Всего: 4



<Spawn> ... Не вижу ничего окейного. Не вижу также где и как объявлена hMutex. Без понятия как используется DLL... Пока все что вижу - это ошибку чреватую переполнением таблицы хэндлов. Если в остальном коде такая же окейность, то... ничего кроме удачи пожелать не смогу.
--------------------
/DVA
PM MAIL WWW   Вверх
<Spawn>
Дата 22.10.2003, 07:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



Да какое переполнение млин, цитата 1 из книги "Системное программирование в Windows 2000" из главы "Синхронизация", автор Ал Вильямс: "Если поток пытается создать объект, который уже существует, вызов создания объекта сработает как вызов открытия объекта ".

Цитата 2 оттуда же: "Create Mutex - создает новый обьект или открывает уже существующий "


Часть ДЛЛ:

Код
library DLLShare;


uses
 SysUtils,
 Classes,
 Windows,
 Dialogs;



var
 ShareData: Pointer; // shared
 hMapFile: THandle=0;
 CurrentDataCount:integer=0;
 [B]hMutex:THandle;[/B]

const
 VirtualFileName = 'ShareDllData';
 DataSize = sizeof (Integer);
 MUTEX_NAME='DLLMutex';


{$R *.res}

function IsValidIndex(Index:Integer):Boolean;
begin
 Result:=(Index>-1) and (Index<CurrentDataCount);
end;

function GetInt(Index:integer):PInteger;
var
i:integer;
begin
 Result:=nil;
 if Assigned(ShareData) then
 begin
   Result:=PInteger(DWORD(@ShareData)+DataSize*Index)
 end;
end;

function GetShareData(Index:integer): integer; stdcall; export;
begin
Result:=0;
if Assigned(ShareData) then
 if IsValidIndex(Index) then
 begin
   Result:=GetInt(Index)^;
 end;
end;

function GetValuesCount:integer; stdcall; export;
begin
Result:=CurrentDataCount;
end;

procedure LockData; stdcall; export;
begin
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 WaitForSingleObject(hMutex, INFINITE);
end;

procedure UnLockData; stdcall; export;
begin
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 ReleaseMutex(hMutex);
 CloseHandle(hMutex);
end;

exports
 AddShareData,
 SetShareData,
 GetShareData,
 DeleteByValue,
 GetValuesCount,
 LockData,
 UnLockData;


При попытке использовать hMutex в UnLockData он равен 0, поэтому приходится его получать при помощи CreateMutex, которая вернет хендл уже существующего мьютекса с таким именем.

Даже если бы это было переполнение таблицы хендлов, как такое моглобы произойти при первом обращении к LockData?confused.gifconfused.gifconfused.gifconfused.gifconfused.gif?? Это просто невозможно.
Пример тестирования. Первый элемент массива равен 1, второй 10, третий 100.
Результат первой попытки получения данных(кодом, который я привел выше, без использования inet_ntoa, т.е. вывод данных при помощи получения их функцией GetShareData):
Код
1
268
100

Второй :
Код
1
256
100

Третий:
Код
1
240
100


Если же убрать вызовы LockData и UnLockData, то результат такой, какой был указан сначала.

Это сообщение отредактировал(а) <Spawn> - 22.10.2003, 07:20


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
Dmitry V.Abramov
Дата 22.10.2003, 08:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 30.9.2003
Где: Saint-Petersburg

Репутация: 5
Всего: 4



Цитата
Да какое переполнение млин, цитата 1 из книги "Системное программирование в Windows 2000" из главы "Синхронизация", автор Ал Вильямс: "Если поток пытается создать объект, который уже существует, вызов создания объекта сработает как вызов открытия объекта ".

Цитата 2 оттуда же: "Create Mutex - создает новый обьект или открывает уже существующий "

Мндасссс...

"Открывает существующий...". А дальше, наверное, что-то типа "Можете плевать на открытые хэндлы - система сама их закроет при завершении процесса" ? Или нет? Если нет, то с чего ты взял, что это тот-же самый хэндл? Может все-таки "хэндл для существующего уже объекта"? Не приходилось открывать один файл двумя программами одновременно? Тоже были одинаковые хэндлы?

Если бы ты читал эту книжку как положено - с начала, то не пропустил бы то место, где рассказывается о ресурсах Windows и о хэндлах в частности. Я же привык объяснять прописные истины лишь тем, кто слушает, а не размахивает наугад раскрытой книжкой... sad.gif

Запусти вот эту "упрощенную" версию твоей же программы:

Код
{$APPTYPE CONSOLE}
program tstmtx;

uses
 Windows;

var
 hMutex:THandle;

const
 MUTEX_NAME='DLLMutex';


procedure LockData;
begin
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 WaitForSingleObject(hMutex, INFINITE);
end;

procedure UnLockData;
begin
 hMutex:=CreateMutex(nil, False, MUTEX_NAME);
 ReleaseMutex(hMutex);
 CloseHandle(hMutex);
end;

begin
 repeat
   LockData;
   write(hMutex, ' ');
   UnlockData;
   write(hMutex, ' ');
 until false;
end.


Выход по Ctrl+C. Во время ее работы сходи в TaskManager и посмотри на строчку Handles:...

Про нулевой hMutex - тоже стало понятно при наличии текста. Но, боюсь, пускаться в объяснения - как бы не пристукнули умной книжной...
--------------------
/DVA
PM MAIL WWW   Вверх
<Spawn>
Дата 22.10.2003, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



Да блин не в этом суть то. Проблема все равно не решиться! Я кажется совсем про другое вопрос задавал!
Да хоть такой код сделать:
Код
try
LockData;
vCount:=GetValuesCount;
for i:=0 to vCount-1 do
begin
  addr.S_addr:=GetShareData(i);
  lbSharedIPList.Items.Add(inet_ntoa(addr));
end;
finally
//Намерено убрали UnLockData
end;


Все равно тот же бред со вторым элементом массива.


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
<Spawn>
Дата 22.10.2003, 09:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Око кары:)
****


Профиль
Группа: Экс. модератор
Сообщений: 2776
Регистрация: 29.1.2003
Где: Екатеринбург

Репутация: 44
Всего: 64



Короче вопрос закрыт я нашел решение


--------------------
"Для некоторых людей программирование является такой же внутренней потребностью, подобно тому, как коровы дают молоко, или писатели стремятся писать" - Николай Безруков.
PM MAIL ICQ   Вверх
stab
Дата 22.10.2003, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 14
Всего: 48



Как мне кажется немного не верно используется мьютексы. Надо бы так:

1. При страте потока\процесса создается\открывается мьютекс.
2. Когда потоку\приложению требуется захватить ресурс он производит это при помощи WaitForSingleObject.
3. Когда ресурс больше не нужен делается ReleaseMutex, т.е. отпускаем ресурс.
4. При завершении потока\процесса делается CloseHandle, хотя для процессов это вроде и не надо, т.к. это за нас делает ОС.

Суммируя все вышесказанное:

Код

library Project2;

uses
 Windows;

const
 MUTEX_NAME = 'zzz';

var // или threadvar для потоков
 hMutex: Cardinal;

var
 SavedProc: TDLLProc;

procedure StartDLL;
begin
 hMutex := CreateMutex(nil, False, MUTEX_NAME);
end;

procedure StopDLL;
begin
 ReleaseMutex(hMutex); // на всякий случай, плохого все равно ни чего из этого не получится
 CloseHandle(hMutex);
end;


procedure LibraryProc(Reason: Integer);
begin
 case Reason of
   DLL_PROCESS_DETACH: StopDLL;

   { если нужно для потоков
   DLL_THREAD_ATTACH: StartDLL;
   DLL_THREAD_DETACH: StopDLL;
   }
 end;

 if Assigned(SavedProc) then
   SavedProc(Reason);
end;


procedure LockData; stdcall;
begin
 WaitForSingleObject(hMutex, INFINITE);
end;

procedure UnLockData; stdcall;
begin
 ReleaseMutex(hMutex);
end;

exports
 LockData,
 UnLockData;

begin
 SavedProc := DllProc;
 DllProc := LibraryProc;
 StartDLL;
end.


попробуй сделать так, может поможет.


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
stab
Дата 22.10.2003, 10:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 14
Всего: 48



Цитата
Короче вопрос закрыт я нашел решение


ай, млин, не успел smile.gif но уж попробуй, плиз... ;)


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0603 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.