Форум: "Основная";
Текущий архив: 2005.10.30;
Скачать: [xml.tar.bz2];
Вниздефрагментация Найти похожие ветки
← →
NightLord © (2005-10-02 01:03) [0]Всем привет! Подскажите как можно записать на винчестер файл без фрагментов? Заранее благодарю.
← →
Германн © (2005-10-02 01:29) [1]А зачем? Объясни.
Поскольку варианты есть, но нет уверенности, что они тебе подойдут. :(
← →
Chuvak © (2005-10-02 01:32) [2]NightLord © (02.10.05 1:03)
Подскажите как можно записать на винчестер файл без фрагментов?
хм...если файл большой по размеру, то придётся попотеть...А такое в принципе возможно?
← →
Германн © (2005-10-02 01:38) [3]2 Chuvak © (02.10.05 01:32) [2]
> А такое в принципе возможно?
ГАРАНТИРУЮ! В принципе возможно. НО...
← →
Chuvak © (2005-10-02 01:43) [4]Германн © (02.10.05 1:38) [3]
В принципе возможно. НО...
НУ? Интересно же...пусть даже гипотетически...
← →
Германн © (2005-10-02 01:50) [5]Ну если интересно, то пожалуйста - Вариант 1: После format буква_диска: первый файл запишется без фрагментации! :)
← →
YurikGL © (2005-10-02 01:51) [6]Можно сначала записать файл, а потом запустить дефрагментатор через shellexecute :)
← →
Chuvak © (2005-10-02 01:57) [7]YurikGL © (02.10.05 1:51) [6]
Можно сначала записать файл, а потом запустить дефрагментатор через shellexecute :)
вопрос был как можно записать на винчестер файл, а не как избавится от фрагментов....
А какие-нить серъёзные варианты ещё есть? ;)
← →
Германн © (2005-10-02 02:07) [8]2 Chuvak © (02.10.05 01:57) [7]
> А какие-нить серъёзные варианты ещё есть? ;)
Серьёзные варианты могут найтись. Но безгеморройные - врядли. Поэтому я и просил уточнить задачу.
← →
Chuvak © (2005-10-02 02:10) [9]Германн © (02.10.05 2:07) [8]
Серьёзные варианты могут найтись.
Всё ходим вокруг да около...а ничего так и не услышали...
← →
drpass © (2005-10-02 02:11) [10]
> После format буква_диска: первый файл запишется без фрагментации!
> :)
На 100% это справедливо только на FAT
> А какие-нить серъёзные варианты ещё есть? ;)
На FAT - открыть диск для прямого доступа с помощью CreateFile, проанализировать его структуру, найти там подходящий непрерывный кусок свободного места, вписать туда свой файл и вручную же внести соответствующие изменения в таблицы размещения. На NTFS, если мне память не изменяет, это не требуется. Ее стратегия размещения файлов и так предполагает запихивание их по возможности целиком в свободные области.
Кстати, а зачем это неблагодарное занятие?
← →
vrem (2005-10-02 09:27) [11]При записи на диск Windows просматривает свободные участки диска, если найден свободный участок размером больше, чем "минимальный размер свободного "участка" диска, то запись начинается в этом участке. если размер меньше, то windows продолжает дальше искать свободный "кусок"
Этот "минимальный размер" задаётся, как раз для уменьшения дефрагментации.
← →
NightLord © (2005-10-02 10:25) [12]> Германн © (02.10.05 01:29) [1]
Я хочу сделадь что-то подобное виндовому дефрагментатору (самому интересно).
← →
Anatoly Podgoretsky © (2005-10-02 13:18) [13]Такое возможно только в однозадачной системе типа ДОС, во всех остальных не гарантируется. Система тоже желает писать на диск.
← →
drpass © (2005-10-02 13:38) [14]Для дефрагментации есть специальный API
← →
homm © (2005-10-02 14:49) [15]2 drpass
A что за API такой? Где под него можно заголовки, примеры найти. Раскрой тему если не трудно, мне тоже было бы интересно узнать.
← →
drpass © (2005-10-02 14:55) [16]Через I/O Control - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/defragmenting_files.asp
← →
NightLord © (2005-10-02 15:19) [17]А можно проделать дефрагментацию без использвания WinApi к примеру из DOS"а ?
← →
alexbou (2005-10-02 16:39) [18]хм.... Озадачился - и вот что набросил за час-два ползания по документации + написании кода...
Предупреждаю - тут много сделано на допущении (например что нет интенсивной записи произвольным образом другими программами :))
Итак - задачи:
Создать файл размером 1 гигабайт без фрагментации
1) получаем размер кластера
2) вычисляем кол-во нужных кластеров
3) ищем блок свободного пространства (получаем номер стартового кластера для этого блока)
4) создаем файл (размером 1 байт =) - почему один а не ноль? потому что нулевые файлы не занимают места вообще (ну кроме как в MFT=)))
5) перемещаем файл-кластер в начало блока
6) расширяем =) вуаля
program creat_notfrag_file;
{$APPTYPE CONSOLE}
uses
Windows, SysUtils, Math;
const
FileNameToCreate = "d:\temp\data.dat";
FileSizeToCreate: Int64 = 1*1024*1024*1024;
const
FILE_READ_ATTRIBUTES = $0080;
FILE_WRITE_ATTRIBUTES = $0100;
FSCTL_GET_NTFS_VOLUME_DATA = $00090064;
FSCTL_GET_VOLUME_BITMAP = $0009006F;
FSCTL_GET_RETRIEVAL_POINTERS = $00090073;
FSCTL_MOVE_FILE = $00090074;
// no comments =)
function OpenVolume(Drive: Char): THandle;
var
DriveName: PChar;
begin
DriveName := PChar("\\.\" + Drive + ":");
Result := CreateFile(DriveName,
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,
0, 0);
end;
type
TNtfsVolumeDataBuffer = record
VolumeSerialNumber : Int64;
NumberSectors : Int64;
TotalClusters : Int64;
FreeClusters : Int64;
TotalReserved : Int64;
BytesPerSector : DWORD;
BytesPerCluster : DWORD;
BytesPerFileRecordSegment : DWORD;
ClustersPerFileRecordSegment : DWORD;
MftValidDataLength : Int64;
MftStartLcn : Int64;
Mft2StartLcn : Int64;
MftZoneStart : Int64;
MftZoneEnd : Int64;
end;
// получить информацию о томе
// свободных кластеров и размер кластера
function GetClustersInfoOfVolume(
VolumeHandle: THandle;
out FreeClusters: Int64;
out SizeOfCluster: DWORD
): Boolean;
var
NtfsVolumeDataBuffer: TNtfsVolumeDataBuffer;
RetSize: DWORD;
begin
Result := false;
if DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_VOLUME_DATA,
nil, 0, @NtfsVolumeDataBuffer, sizeof(NtfsVolumeDataBuffer),
RetSize, nil) then
begin
FreeClusters := NtfsVolumeDataBuffer.FreeClusters;
SizeOfCluster := NtfsVolumeDataBuffer.BytesPerCluster;
Result := true;
end;
end;
const
BufferSize = 4096;
type
TVolumeBitmapBuffer = record
StartingLcn : Int64;
BitmapSize : Int64;
Buffer : array [0..BufferSize] of Byte;
end;
PVolumeBitmapBuffer = ^TVolumeBitmapBuffer;
// возвращает LCN для первого же найденого блока
// свободных кластеров, куда влезет файл
// !!! Это функция не учитывает сам файл, поэтому
// не юзать после создания файла заданного размера
function SearchFreeSpaceBlockForFileSpawn(
VolumeHandle: THandle;
ReqBlockSizeInClusters: Cardinal
): Cardinal;
var
StartLcn: Int64;
Bitmap: TVolumeBitmapBuffer;
pBitmap: PVolumeBitmapBuffer;
RetSize: DWORD;
RetStatus: Cardinal;
StartFree: Int64;
NumFree: Int64;
idx: Int64;
begin
Result := Cardinal(-1);
StartFree := -1;
NumFree := 0;
StartLcn := 0;
pBitmap := @Bitmap;
FillChar(Bitmap, SizeOf(Bitmap), 0);
repeat
SetLastError(0);
DeviceIoControl(VolumeHandle, FSCTL_GET_VOLUME_BITMAP,
@StartLcn, SizeOf(Int64),
pBitMap, SizeOf(Bitmap), RetSize, nil);
RetStatus := GetLastError;
if (RetStatus <> 0) and (RetStatus <> ERROR_MORE_DATA) then
begin
Writeln("FSCTL_GET_VOLUME_BITMAP");
Break;
end;
// обход ограничений компилятора на использования Int64 в циклах for
idx := 0;
while idx < Min(pBitmap.BitmapSize, BufferSize * 8) - 1 do
begin
if pBitmap.Buffer[idx div 8] and (1 shl (idx mod 8)) = 0 then
begin
if StartFree = -1 then
begin
StartFree := pBitmap.StartingLcn + idx;
NumFree := 1;
end
else
Inc(NumFree);
end
else
StartFree := -1;
if (StartFree <> -1) and (NumFree = ReqBlockSizeInClusters) then
begin
Result := StartFree;
Writeln;
Exit;
end;
Inc(idx);
end;
if RetStatus = ERROR_MORE_DATA then
StartLcn := Bitmap.StartingLcn + BufferSize * 8
else
Break;
Write(".");
until False;
Writeln;
end;
type
TMovieFileData = record
FileHandle: THandle;
StartingVcn: Int64;
StartingLcn: Int64;
ClusterCount: DWORD;
end;
← →
alexbou (2005-10-02 16:40) [19]
// Перемещает кластер файла
function MoveFileCluster(
hVolume, hFile: THandle;
VCN: Cardinal; LCN: Cardinal
): Boolean;
var
MovieFileData: TMovieFileData;
RetSize: DWORD;
begin
with MovieFileData do
begin
FileHandle := hFile;
StartingVcn := VCN;
StartingLcn := LCN;
ClusterCount := 1;
end;
Result := DeviceIoControl(hVolume, FSCTL_MOVE_FILE,
@MovieFileData, SizeOf(TMovieFileData),
nil, 0,
RetSize, nil);
end;
// Создаем нужный файл нужного размера
function SpawnFile(
hVolume: THandle;
TargetCluster: Int64;
FileName: &String; FileSize: DWORD
): Boolean;
var
hFile: THandle;
begin
Result := False;
hFile := CreateFile(FileNameToCreate,
FILE_READ_ATTRIBUTES or FILE_WRITE_ATTRIBUTES
or GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_WRITE or FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 0, 0);
if hFile = INVALID_HANDLE_VALUE then
Exit;
SetFilePointer(hFile, 1, nil, FILE_BEGIN);
SetEndOfFile(hFile);
FlushFileBuffers(hFile);
CloseHandle(hFile);
// перемещаем в нужный кластер (начало большого пространства)
hFile := CreateFile(FileNameToCreate,
FILE_READ_ATTRIBUTES or FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, 0, 0);
if hFile = INVALID_HANDLE_VALUE then
Exit;
if not MoveFileCluster(hVolume, hFile,
0, TargetCluster) then
begin
Writeln("FSCTL_MOVE_FILE");
Exit;
end;
FlushFileBuffers(hFile);
CloseHandle(hFile);
// расширяем файл
hFile := CreateFile(FileNameToCreate,
FILE_READ_ATTRIBUTES or FILE_WRITE_ATTRIBUTES
or GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_WRITE or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, 0, 0);
SetFilePointer(hFile, FileSize, nil, FILE_BEGIN);
SetEndOfFile(hFile);
FlushFileBuffers(hFile);
CloseHandle(hFile);
end;
var
VolumeHandle: THandle;
FreeClusters: Int64;
SizeOfCluster: DWORD;
NeededClusters: DWORD;
TargetCluster: Int64;
begin
VolumeHandle := OpenVolume(FileNameToCreate[1]);
if VolumeHandle = INVALID_HANDLE_VALUE then
begin
Writeln("OpenVolume");
Exit;
end;
if not GetClustersInfoOfVolume(VolumeHandle,
FreeClusters, SizeOfCluster) then
begin
Writeln("GetClustersInfoOfVolume");
Exit;
end;
NeededClusters := FileSizeToCreate div SizeOfCluster
+ FileSizeToCreate mod SizeOfCluster;
if (NeededClusters > FreeClusters) then
begin
Writeln("NeededClusters > FreeClusters");
Exit;
end;
TargetCluster :=
SearchFreeSpaceBlockForFileSpawn(VolumeHandle, NeededClusters + 1);
if (TargetCluster = -1) then
begin
Writeln("TargetCluster = ?");
Exit;
end;
SpawnFile(VolumeHandle, TargetCluster, FileNameToCreate, FileSizeToCreate);
CloseHandle(VolumeHandle);
end.
← →
homm © (2005-10-02 19:43) [20]2 alexbou
Ну ты и заморил ;) клево блин. Только вот 2 вопроса
1) А чейто новоиспеченый файл в "Дефрагментатор диска" красным светится.
2) А на FAT то работает? Диск не грохнет?
← →
alexbou (2005-10-03 17:55) [21]Для ФАТа нужно брать другую структуру для FSCTL_GET_VOLUME_BITMAP...
А что касательно фрагментации.... Мда.... Проверил - раз на раз не приходится, и у меня бывает фрагментация... =(
← →
alexbou (2005-10-03 18:06) [22]drpass
> На NTFS, если мне память не изменяет, это не требуется.
> Ее стратегия размещения файлов и так предполагает запихивание
> их по возможности целиком в свободные области.
Увы и ах - это вовсе не гарантируется.... Иначе не было бы фрагментации файлов :) Была бы тогда просто фрагментация свободного пространства
← →
drpass © (2005-10-03 23:28) [23]
> Увы и ах - это вовсе не гарантируется.... Иначе не было
> бы фрагментации файлов :)
Ну, до тех пор, пока это самое свободное место есть... Если учесть, что NTFS выбирает место "с запасом" - для возможного будущего роста файла, фрагментация начинает проявляться (и угрожающе быстро расти) примерно при 50%-60% заполнении тома
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.10.30;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.054 c