Могу ли я создать уникальное имя файла на основе ProcessID и ThreadID? - PullRequest
3 голосов
/ 07 ноября 2008

У меня есть веб-приложение delphi (Win32), которое может работать как приложение CGI, ISAPI или Apache DLL. Я хочу иметь возможность сгенерировать уникальный префикс имени файла (уникальный для всех текущих запросов в данный момент) и понять, что лучший способ сделать это - использовать processID (для обработки режима CGI), а также threadID (для обработки). режим dll).

Как получить уникальный идентификатор процесса и идентификатор потока в Delphi?

Будут ли они уникальными в ситуации с многоядерным процессором или мультипроцессором (на одном компьютере с веб-сервером)?

Редактировать: обратите внимание, что я был против этого подхода, и поэтому принятый ответ использует другой метод для создания временных имен файлов

Ответы [ 7 ]

5 голосов
/ 07 ноября 2008

у вас есть много хороших идей, представленных здесь.

Создает ли он также пустой файл для «блокировки» имени?

нет; я полагаю, что мы полагаемся на Windows для обеспечения того, чтобы одно и то же имя временного файла никогда не указывалось дважды на одном компьютере с момента загрузки.

есть ли любой шанс столкновения, если существует задержка в доли секунды между генерацией имени и созданием файла (если мне нужно создать файл самостоятельно).

нет; это было бы очень плохо.

вот процедура, которую я использовал для получения временного файла.

function GetTemporaryFileName:string;
var
  Path, FileName: array[0..MAX_PATH] of Char;
begin
  Win32Check(GetTempPath(MAX_PATH, Path) <> 0);
  Win32Check(GetTempFileName(Path, '~EX', 0, FileName) <> 0);
  Result:=String(Filename);
end;

вместо этого вы можете использовать FileGetTempName () из JclFileUtils.pas в JCL.

5 голосов
/ 08 ноября 2008

Windows предоставляет функциональность для создания гарантированных уникальных имен файлов. Нет необходимости создавать свои собственные:

Вот оболочка Delphi вокруг этой функциональности:

function CreateTempFileName(aPrefix: string): string;
var
  Buf: array[0..MAX_PATH] of Char;
  Temp: array[0..MAX_PATH] of Char;
begin
  GetTempPath(MAX_PATH, Buf);
  if GetTempFilename(Buf, PChar(aPrefix), 0, Temp) = 0 then
  begin
    raise Exception.CreateFmt(sWin32Error, [GetLastError, SysErrorMessage(GetLastError)]);
  end;
  Result := string(Temp);
end;
4 голосов
/ 07 ноября 2008

Не могли бы вы вместо этого использовать GUID ?

Редактировать: Если бы вы сказали впервые, проверьте следующие две функции

CreateGuid
GuidToString
3 голосов
/ 08 ноября 2008

1) Как получить уникальный идентификатор процесса и ThreadID в Delphi:

Ответ:
ПРИМЕЧАНИЕ. Убедитесь, что вы добавили «windows» в раздел об использовании в разделе реализации
ПРИМЕЧАНИЕ. Кардиналы - это 32-разрядные целые числа без знака в диапазоне от 0 до 4294967295

.
implementation
uses Windows;

procedure MySolution();
var
  myThreadID:Cardinal;  
  myProcessID:Cardinal;
begin
  myThreadID := windows.GetCurrentThreadID;
  myProcessID := windows.GetCurrentProcessId;
end;

2) Будут ли они уникальными в ситуации с многоядерным / многопроцессорным режимом (на одном компьютере с веб-сервером)?
Ответ: Да.

Идентификатор процесса действителен с время создания процесса до процесс был прекращен и уникален во всей системе. (Не уникальный для процессора)

Пока поток не завершится, идентификатор потока однозначно идентифицирует поток по всей системе. (Опять же, общесистемная, не уникальная для процессор)

3 голосов
/ 07 ноября 2008

Идентификаторы процессов не гарантированно будут уникальными в Windows. Они, безусловно, уникальны для жизни процесса, но как только процесс умирает, его идентификатор может быть немедленно использован повторно. Я не уверен насчет ThreadID. Если это временные файлы, вы можете использовать что-то эквивалентное tmpfile или tmpnam (функции C, но я предполагаю, что Delphi имеет аналог).

Поскольку Джейми опубликовал GUID, может быть лучше.

2 голосов
/ 07 ноября 2008

Лучше, чем любой из этих вариантов, вы должны использовать системную функцию _tempnam . Возвращает случайное имя файла в каталоге для файла, который не существует. Если вы хотите, вы можете указать префикс _tempnam, чтобы создаваемый вами файл был узнаваемо вашим. Если вы предоставляете уникальный префикс, не нужно беспокоиться о том, что кто-то откроет ваш файл. Однако есть и другое решение.

_tempnam подходит только в том случае, если вы хотите поместить файл в произвольный каталог. Если вас не волнует, что каталог является системным временным каталогом, используйте tempfile_s . Он также создаст файл для вас, так что не беспокойтесь о состоянии гонки ... Ошибки будут появляться только в том случае, если вы попытаетесь открыть больше временных файлов, чем может обработать система. Большим недостатком tempfile_s является то, что файл исчезнет, ​​как только вы его закроете.

РЕДАКТИРОВАТЬ: я получил отрицательный голос, потому что это функция C. У вас есть доступ к среде выполнения C, импортировав их в Delphi. Посмотрите на некоторые примеры с msvcrt.dll здесь .

function _tempnam(const Dir: PChar, const Prefix: PChar): PChar; cdecl;
  external 'msvcrt.dll' name '_tempnam';
1 голос
/ 07 ноября 2008

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

Используйте GetCurrentProcessID и GetCurrentThreadID Win32 вызывает для доступа к этим двум идентификаторам.

...