МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
Кафедра ЕОМ
КУРСОВИЙ ПРОЕКТ
з предмету “Системне програмне забезпечення”
на тему:
“Розробка системної утиліти для дефрагментації диску”
ЗАВДАННЯ НА КУРСОВИЙ ПРОЕКТ
Завданням курсового проекту є розробка системної утиліти «дефрагментація жорсткого диску». Утиліта повинна здійснювати дефрагментацію інформації, що знаходиться на жорсткому диску.
Утиліта повинна мати такі функції:
пошук фрагментованої інформації;
аналіз дискового накопичувача;
загальне відображення фрагментів файлів, а також вільного місця;
відображення кластерів, їх пошук;
дефрагментація фрагментованої інформації.
Утиліта повинна бути орієнтованою на операційну систему сімейства Windows.
Мова написання системної утиліти: C/C++
АНОТАЦІЯ
У даному курсовому проекті розроблено утиліту, за допомогою якої можна здійснювати пошук і дефрагментацію жорстких дисків, а також пошук і перегляд інформації про кількість фрагментованих файлів і дерикторій.
Програма розроблена за допомогою Visual Studio 2010 і працює на базі платформи .NET з використанням WinApi функцій.
Програма виконує сканування, оновлення списку пристроїв, пошук файлів, дефрагментацію, відображення кластерів і додаткової інформації.
ЗМІСТ
Вступ 5
1.Теореритчні відомості 6
2. Аналіз завдання та вибір напрямку розробки 10
2.1. Аналіз завдання 10
2.2. Вибір напрямку розробки 10
2.2.1. Вибір середовища та мови програмування 10
2.2.2. Вибір технології програмування 11
2.2.3. Вибір та розробка структур даних і функцій 11
3. Розробка компонент програмної реалізації 15
3.1. Розробка 15
3.2. Структурні елементи утиліти 15
3.3. Алгоритм роботи утиліти 18
3.3.1. Розробка алгоритму отримання інформації про логічні диски (функція list<char> GetLetters()) 18
3.3.2. Розробка алгоритму отримання інформації про логічні диски (функція void Dir(char *root)) 19
3.3.3. Розробка алгоритму пошуку файлів в директорії (функція void GetFiles(char* way)) 20
3.3.4. Розробка алгоритму переміщення блоків кластерів файлу (функція int GetClusters(const char* name,bool d)) 21
3.3.5. Розробка алгоритму отримання інформації про кластери, запис в які заборонений (void ProcessVolume(HANDLE VolumeName)) 23
4. Інструкція користувача та результати тестування 26
4.1. Інструкція користувача. 26
4.1.1. Вимоги для запуску 26
4.1.2. Вікно утиліти 26
4.2. Результати тестування 30
Висновок 32
Список використаних джерел 33
Додаток 1. Блок-схема алгоритму 34
Додаток 2. Код програми 35
Вступ
Недоліком фрагментації є низька швидкість роботи з файлами. Неможливість обробити файл послідовно призводить до уповільнення роботи з диском. Звичайним користувачам рідко потрібна така висока швидкість роботи з диском, втрати могли б бути несуттєвими. Але в Windows віртуальна пам'ять знаходиться на тому ж самому диску, що і файли. А Windows використовує віртуальну пам'ять (або файл підкачки) регулярно. Тому у випадку сильно фрагментованого диска комп'ютер може починати сильно гальмувати не тільки при роботі з диском.
Великі дані записуються на диск в декількох кластерах. Якщо місця для запису певного файлу достатньо, то всі кластери розміщуються послідовно. Однак якщо простір частково заповнений, великому файлу може не знайтися цільної вільної області для його розміщення. У такому випадку дані будуть записані у вільні кластера, за умови, що їх сумарний обсяг задовольняє даний файл. В цьому випадку файл записується у вигляді декількох фрагментів. Більше того: у багатьох файлових системах (приклад FAT32) початок файлу записується в початок кластера, отже, якщо сам файл або його частину за об'ємом менше розміру кластера, то місце, що залишилося в кластері залишається невикористаним. Тому фрагментованість диска обернено пропорційна ефективності використання його простору.
Актуальністю розробки системної утиліти дефрагментації диску є вирішення проблеми фрагментації , оскільки хаотично розміщенні кластери одного файлу збільшують час читання файлу.
1.Теореритчні відомості
Дефрагментація – процес оновлення та оптимізації логічної структури розділу фізичного диску з метою забезпечити зберігання файлів у неперервній послідовності кластерів. Після дефрагментації прискорюється читання та запис файлів, а відповідно і робота програм.
Іншими словами, дефрагментація - це процес пошуку і об’єднання фрагментованих файлів і папок. Програма переміщує дані таким чином, щоб кожний із файлів займав на диску один неперервний фрагмент, а вільне місце об’єднувалося в єдину неперервну ділянку.
Чим частіше записуються і видаляються файли, тим більше жорсткий диск стає фрагментованим. Це значно знижує швидкість опрацювання даних і збільшує навантаження на процесор, крім цього фрагментований диск швидше виходить з ладу (зношується).
Довгі файли займають декілька кластерів. Якщо запис проводиться на пустий диск, то кластери, що належать одному файлу, записуються підряд (див. рис.1.1).
/
Рис.1.1. Запис кластерів на пустий диск
Якщо диск переповнений, то на ньому може не бути цілісної області, достатньої для розміщення файлу. Проте, файл все-таки запишеться, якщо на диску багато дрібних ділянок, сумарний розмір яких достатній для запису. В цьому випадку файл записується у вигляді декількох фрагментів(див.рис.1.2).
/
Рис.1.2. Запис кластерів на переповнений диск
Процес розбиття файлу на невеликі фрагменти при записі на диск називається фрагментацією (процес дроблення чого-небудь на безліч дрібних розрізнених фрагментів або ефект, що виникає у процесі активної роботи з файлами (створення, видалення, переміщення, зміна розмірів) і виражається у відсутності на жорсткому диску достатньої кількості послідовних вільних блоків). На фрагментованому диску вільні блоки розкидані по всій поверхні диска, і при подальшій роботі з диском, це приводить до фрагментації даних. Якщо на диску багато фрагментованих файлів, швидкість читання жорсткого диску зменшується, оскільки пошук кластерів, в яких зберігаються файли, вимагає часу.
Проте, бувають виключення. Наприклад, при використанні флеш-пам'яті час пошуку не залежить від розташування секторів, і практично рівний нулю, тому для них дефрагментація не потрібна.
Дефрагментація найчастіше використовується для таких файлових систем, як File Allocation Table (FAT) та New Technology File System (NTFS) для MS-DOS і Microsoft Windows, оскільки в програмах для роботи з ними зазвичай не передбачено ніяких засобів для попередження та запобігання фрагментації, і такий ефект з'являється навіть на майже порожньому диску і невеликому навантаженні.
Програми дефрагментації запускаються аналогічно до програм сканування дисків на виявлення помилок. Звичайно програма не вимагає дефрагментації, поки вміст фрагментованих файлів не досяг 20%, але доцільним є використання дефрагментації і при 6-8 %. Заглибимося трохи в логічний пристрій жорсткого диска комп’ютера, на якому зберігаються всі наші файли. Він являє собою пачку керамічних дисків – «млинців» з магнітним покриттям. На них і записується вся інформація за допомогою блоку записуючих і читаючих головок, які розташовані між усіма цими дисками.
При форматуванні диска відбувається його розмітка на сектори, кожен з яких може містити 512 байт даних. Це дуже мало, тому сектора об’єднані в більш велику логічну одиницю – кластери. Один кластер містить кратне двійці кількість секторів – 2, 4, 8, 16 і т.д. Зазвичай один кластер може містити 4 кілобайти інформації, хоча при форматуванні є можливість вибрати іншу величину.
Зрозуміло, що розміри файлу зазвичай набагато більше, ніж розмір одного кластера, тому він може займати і два, і десять, і сто кластерів. При цьому в одному кластері не може бути двох маленьких файлів – тільки один, навіть якщо він займає тільки частину кластера. Тобто файл розміром в 10 байт все одно займає цілий кластер в 4 кілобайти, просто вільна частина кластера виявляється «втраченої» – в неї нічого більше не можна записати, поки файл його займає. Можете в цьому переконатися – у властивостях будь-якого файлу написано, який його реальний розмір, і скільки місця він займає на диску – цифри помітно відрізняються. Але це вже інше питання, хоча теж цікавий.
При запису інформації на диск є одна особливість, про яку не всі знають. Інформація на нього записується послідовно. Тобто на чистий диск вона починає записуватися в перший, другий, третій кластери і так далі, до останнього по порядку. Але коли вільні кластери кінчаються, відлік починається спочатку. Від початку диска знаходиться перший порожній кластер, записується туди частину файлу, а наступна частина записується в наступний вільний, який не обов’язково може бути наступним по порядку – він може знаходитися зовсім в іншій частині диска. Якщо файл великий, він може бути розкиданий по всьому диску шматками по 4 кілобайти. Щоб потім його прочитати, читаючою голівках доведеться з шаленою швидкістю кидатися по всьому диску, втрачаючи час на зайві переміщення і виділяючи зайве тепло. Це не тільки сповільнює читання файлів, а значить – і всю роботу комп’ютера, але і приводить до прискореного зносу механічних частин жорсткого диска.
Чому утворюється такий розкид? Та просто в процесі роботи якісь файли записуються, інші видаляються. Їх розміри не співпадають, тому великий файл може потрапити туди, де раніше було десять маленьких, і все в різних місцях. Кожен окремий шматок файлу називається фрагментом, а такий файл фрагментованим.
Якщо це складно зрозуміти – розглянемо приклад з книгою. У ній кожна сторінка – кластер, на сторінці нехай буде дві колонки – тобто два сектори. Одна голова в книзі може займати не одну сторінку – кластер, а багато. При цьому глави йдуть по порядку – тобто, фрагментації немає.
А тепер уявімо книгу фрагментовану. Прочитали одну колонку, бачимо напис – «продовження на сторінці 125, 2-а колонка». Гаразд, йдемо туди, читаємо, а в кінці знову «продовження на сторінці 45, 1-а колонка». Погодьтеся, ми будемо більше гортати таку книгу, ніж справді читати, а незабаром закинемо її.
Щоб зібрати частини файлів разом і переписати їх на диск у сусідні кластери, існують спеціальні програми – дефрагментатори. Вони просто беруть всі частини одного файлу і записують їх підряд, звільняючи кластери під нього по порядку. І так – для всіх файлів. Зрештою, вся інформація стає впорядкованою і читаючі головки легко і швидко знаходять її – адже їм вже не доводиться судорожно бігати по всьому диску. Це дуже добре позначається на загальній продуктивності комп’ютера – це навіть на око помітно. Процес з’єднання частин – фрагментів в єдиний файл називають дефрагментацією.
З цієї причини рекомендується регулярно проводити дефрагментацію всіх жорстких дисків комп’ютера. Не кожен день, звичайно, але раз на місяць бажано. А якщо на комп’ютері часто встановлюються ігри, програми, скопійовані або видаляються фотографії або фільми – коротше кажучи, активно використовується файлова система, то можна проводити дефрагментацію і пару раз на місяць. Занадто часто теж не треба, адже це серйозне навантаження на вінчестер – переміщати сотні тисяч файлів, тому шкоди може бути більше, ніж користі. Фрагментація наростає не так швидко, як здається, тому зазвичай одного разу на місяць цілком достатньо.
2. Аналіз завдання та вибір напрямку розробки
2.1. Аналіз завдання
Виходячи з поставленого завдання програма мусить забезпечувати:
Фрагментацію файлів.
Підтримку файлових систем NTFS та FAT32.
Відображення кластерів.
Також користувачу потрібно надати простий та зрозумілий користувацький інтерфейс.
Отже, програмі необхідно реалізувати такі функції:
отримання доступ до дисків вінчестера, а також інших зовнішніх запам’ятовуючих пристроїв;
отримання доступів до всіх файлів та папок;
відображення фізичної структури файлів, тобто їх кластерів;
отримання повної інформації про файли;
функція переривання форматування та виходу з програми;
зручний інтерфейс.
Отже ця утиліта надасть змогу без додаткових зусиль отримувати інформацію про форматовані файли системи.
2.2. Вибір напрямку розробки
2.2.1. Вибір середовища та мови програмування
Цільовою мовою програмування було обрано C++. Дана мова програмування широко використовується для розв’язання задач різного рівня складності. Перевагами даної мови порівняно з іншими є широкий набір бібліотек класів для роботи з стрічками, файлами, різноманітними структурами даних.
Оскільки утиліта орієнтована на сімейство операційних систем Windows, то для її розробки будуть використовуватись Windows API функції - набір базових функцій інтерфейсів програмування. Вони дадуть змогу просто і зручно отримувати інформацію про потрібні нам параметри. Нижче буде наведено основні функції які нам потрібні для роботи та їх опис.
2.2.2. Вибір технології програмування
Технологією програмування було обране процедурне програмування. Виконання програми зводиться до послідовного виконання операторів з метою перетворення початкового стану пам'яті, тобто значень вихідних даних, в заключне, тобто в результати. Таким чином, з точки зору програміста є програма і пам'ять, причому перша послідовно оновлює вміст останньої.
Процедурна мова програмування надає можливість програмісту визначати кожен крок у процесі рішення задачі. Особливість таких мов програмування полягає в тому, що завдання розбиваються на кроки і вирішуються крок за кроком. Використовуючи процедурну мову, програміст визначає мовні конструкції для виконання послідовності алгоритмічних кроків.
2.2.3. Вибір та розробка структур даних і функцій
За допомогою функції GetVolumeInformation можна отримати інформацію про файлову систему логічного розділу і її властивості.
GetVolumeInformation (
LPCTSTR lpRootPathName, //Кореневий каталог
LPTSTR lpVolumeNameBuffer, //Мітка розділу
DWORD nVolumeNameSize, //Обсяг розділу
LPDWORD lpVolumeSerialNumber, //Серійний номер
LPDWORD lpMaximumComponentLength, //Макс. довжина імен
LPDWORD lpFileSystemFlags, //Системні прапорці
LPTSTR lpFileSystemNameBuffer, //Назва файлової системи
DWORD nFileSystemNameSize //Довжина назви
);
За допомогою функції GetDiskFreeSpace можна отримати інформацію про обсяг вільного простору на диску.
GetDiskFreeSpace (
LPCTSTR lpRootPathName, //Кореневий каталог
LPDWORD lpSectorsPerCluster, //Число секторів в кластері
LPDWORD lpBytesPerSector, //Число байтів в секторі
LPDWORD lpNumberOfFreeClusters, //К-ть вільних кластерів
LPDWORD lpTotalNumberOfClusters //Загальна к-ть кластерів
);
Функція DeviceIoControl здійснює безпосередню взаємодію з драйвером пристрою, посилаючи йому команду, що дозволяє управляти цим пристроєм або отримати про нього інформацію. Це багатоцільова функція управління введенням- виведенням (IOCTL). Фактично, DeviceIoControl являє собою безліч функцій, вид яких задається її параметром dwIoControlCode. У даному розділі розглянемо використання цієї функції для отримання інформації про диски.
За допомогою функції DeviceIoControl можна отримати доступ не тільки до логічних, а й до фізичних дисків. Дескриптор диска, інформацію про який ви хочете отримати, задається першим параметром функції. Цей дескриптор повертається функцією CreateFile, яка повинна бути попередньо викликана. При цьому повинні бути виконані наступні вимоги:
щоб відкрити фізичний жорсткий диск з номером Х, шлях до файлу - аргумент lpFileName у виклику CreateFile повинен мати форму "\\.\PHYSICALDRIVEx". Номери жорсткого диска починаються з нуля. Наприклад: "\\.\PHYSICALDRIVE0" - це перший фізичний диск комп'ютера користувача;
щоб відкрити один з логічних дисків, на які розбитий фізичний диск, шлях до файлу - аргумент lpFileName у виклику CreateFile повинен мати форму "\\.\X:", де х - буква диска (регістр літери не має значення);
аргумент dwCreationDistribution у виклику CreateFile повинен мати прапор OPEN_EXISTING;
при відкритті жорсткого диска ви повинні в аргументі dwShareMode у виклику CreateFile встановити прапор FILE_SHARE_WRITE.
За допомогою функції FindFirstFile можна отримати інформацію про перший файл в директорії.
HANDLE FindFirstFile(
LPCTSTR lpFileName, // ім’я файла
LPWIN32_FIND_DATA lpFindFileData // буфер даних
);
За допомогою функції FindNextFile можна отримати інформацію про наступний файл в директорії.
BOOL FindNextFile(
HANDLE hFindFile // дескриптор пошуку
LPWIN32_FIND_DATA lpFindFileData // буфер даних
);Структура містить початковий логічний кластер.
typedef struct {
LARGE_INTEGER StartingLcn; // початковий кластер
} STARTING_LCN_INPUT_BUFFER, *PSTARTING_LCN_INPUT_BUFFER;
Структура містить масив кластерів, що належать файлу.
typedef struct RETRIEVAL_POINTERS_BUFFER {
DWORD ExtentCount; // к-ть кластерів
LARGE_INTEGER StartingVcn; // початковий віртуальний кластер
struct {
LARGE_INTEGER NextVcn; // наступний віртуальний кластер
LARGE_INTEGER Lcn; // логічний кластер
} Extents[1];
} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER;
Структура містить початковий віртуальний кластер.
typedef struct {
LARGE_INTEGER StartingVcn; // початковий кластер
} STARTING_VCN_INPUT_BUFFER, *PSTARTING_VCN_INPUT_BUFFER;
Структура містить набір групу послідовних кластерів, що належать файлу
typedef struct {
HANDLE FileHandle; // дескриптор файлу
LARGE_INTEGER StartingVcn; // початковий віртуальний кластер
LARGE_INTEGER StartingLcn; // початковий логічний кластер
DWORD ClusterCount; // к-ть сластерів
} MOVE_FILE_DATA, *PMOVE_FILE_DATA;
Структура містить інформацію про логічний розділ.
typedef struct {
PARTITION_STYLE PartitionStyle; // Стиль розділу
LARGE_INTEGER StartingOffset; // Зміщення початку
LARGE_INTEGER PartitionLength; // Довжина розділу
DWORD PartitionNumber; // Номер розділу
BOOLEAN RewritePartition; // Повертає розділ
union {
PARTITION_INFORMATION_MBR Mbr; // Стиль розділу Mbr
PARTITION_INFORMATION_GPT Gpt; // Стиль розділу Gpt
};
} PARTITION_INFORMATION_EX;
3. Розробка компонент програмної реалізації
3.1. Розробка
Для ефективного розв’язання поставленої задачі, усю програму було розділено на декілька функцій, кожна з яких чітко має своє призначення і виконує певні дії у загальному алгоритмі функціонування програми:
Функція main.
GetLetters.
Search.
Dir.
GetFiles.
GetClusters.
ProcessVolume.
FindFreeBlock.
Defrag.
3.2. Структурні елементи утиліти
Табл. 3.1 Структурні елементи утиліти
Назва поля
Опис
Змінні
int files;
Містить кількість просканованих файлів і дерикторій на логічному диску
bool sh;
Відповідає за відображення проміжних результатів під час сканування диску
ULONG64 MaxLcn;
Максимальний логічний сластер
list<string> frag_files;
Список фрагментованих файлів і дерикторій
DWORD ClusterSize;
Розмір кластера вибраного логічного диску
Табл.3.1. продовження
struct {
ULONG64 Start;
ULONG64 End;
} Excludes[3];
Масив кластерів в які не можна записувати
дані
Функції
void main()
Головна функція.
List<char> GetLetters()
Отримує логічні диски.
Не приймає жодних значень.
Повертає список логічних дисків.
Void Search(char let)
Викликає пошук всіх файлів і м. к торій на логічному диску.
Приймає на вхід букву логічного диска.
Не повертає жодних значень.
Void Dir(char *root)
Шукає всі піддиректорії в даній директорії.
Приймає на вхід рядок з директорією.
Не повертає жодних значень.
Void GetFiles(char* way)
Шукає всі файли в даній директорії.
Приймає на вхід рядок з директорією
Не повертає жодних значень.
Int GetClusters(const char* name,bool d)
Визначає чи кластери файла є послідовними / переміщає блоки кластерів файла
Приймає на вхід рядок з ім’ям файлу, змінну, що визначає виконувати першу чи другу операцію.
Повертає к-ть блоків кластерів/одиницю при успішному виконанні.
Табл.3.1. продовження
void ProcessVolume(HANDLE VolumeName)
Отримує інформацію про кластери, запис в які заборонений.
Приймає на вхід дескриптор логічного диска
Не повертає жодних значень.
int FindFreeBlock(HANDLE VolumeHandle,ULONG64 MinimumLcn,DWORD MinimumSize,ULONG64 *BeginLcn,ULONG64 *EndLcn)
Виконує пошук вільного блоку для розміщення файлу чи директорії.
На вхід приймає дескриптор логічного диску для пошуку, логічний сектор з якого потрібно починати пошук, розмір який потрібно шукати, вказівник на змінну в яку буде записуватись початковий логічний кластер для запису, вказівник на змінну в яку записується кінцевий логічний кластер для запису.
Не повертає жодних значень.
int Defrag()
Перебирає всі фрагментовані файли і відправляє їх на де фрагментацію.
Не приймає на вхід жодних значень.
Повертає 1 при успішному виконанні.
3.3. Алгоритм роботи утиліти
3.3.1. Розробка алгоритму отримання інформації про логічні диски (функція list<char> GetLetters())
Рис 3.1. Граф-схема алгоритму отримання інформації про логічні диски
Розглянемо алгоритм роботи функції list<char> GetLetters():
Перебираються всі букви, які можуть отримати логічні диски.
За допомогою функції CreateFile відкриваємо диск.
Перевіряємо чи диск відкрився:
якщо диск не відкрився завершуємо роботу з ним;
якщо диск відкрився продовжуємо роботу з ним.
Відкриваємо диск для отримання інформації про нього DeviceIoControl з IOCTL_DISK_GET_PARTITION_INFO_EX, GetVolume Information, GetDiskFreeSpace.
Закриваємо диск з яким працювали.
Після отримання інформації про диски нам потрібно ввести букву потрібного нам диску і здійснити пошук всіх файлів і директорій на логічному диску за допомогою функції void Search(char let), після чого викликаємо функцію Dir.
3.3.2. Розробка алгоритму отримання інформації про логічні диски (функція void Dir(char *root))
Рис 3.2. Граф-схема алгоритму отримання інформації про кластери
Розглянемо алгоритм роботи функції void Dir(char *root):
Викликаємо функцію для отримання інформації про кластери GetClusters.
Шукаємо в даній директорії піддиректорію FindFirstFile.
Перевіряємо директорію:
якщо піддиректорії не знайдено завершуємо роботу;
якщо знайдено піддиректорію продовжуємо роботу .
Викликаємо функцію GetFiles для отримання файлів.
Викликаємо функцію Dir для отримання піддиректорій.
Продовжуємо повторювати попередні 3 пункти поки функція FindNextFile повертає значення.
3.3.3. Розробка алгоритму пошуку файлів в директорії (функція void GetFiles(char* way))
Рис 3.3. Граф-схема алгоритму пошуку файлів директорії
Розглянемо алгоритм роботи функції void GetFiles(char* way):
Шукаємо в даній директорії піддиректорію FindFirstFile.
Перевіряємо директорію:
якщо піддиректорії не знайдено завершуємо роботу;
якщо знайдено піддиректорію продовжуємо роботу.
Викликаємо функцію GetClusters для отримання інформації про кластери.
Продовжуємо повторювати попередні 2 пункти поки функція FindNextFile повертає значення.
3.3.4. Розробка алгоритму переміщення блоків кластерів файлу (функція int GetClusters(const char* name,bool d))
Розглянемо алгоритм роботи функції int GetClusters(const char* name,bool d):
За допомогою функції CreateFile відкриваємо файл або директорію.
За допомогою функції CreateFile відкриваємо диск.
Перевіряємо файл або директорію чи диск:
якщо файл або директорію чи диск не відкрився завершуємо роботу з ними;
якщо файл або директорію чи диск відкрився продовжуємо роботу з ними.
За допомогою функції GetFileSizeEx отримуємо розмір файлу або директорії.
Відкриваємо файл або директорію для отримання інформації про кластери за допомогою функції DeviceIoControl з параметром FSCTL_GET_RETRIEVAL_ POINTERS.
Перевірка 2-го параметру:
якщо він рівний 0 повертаєм к-ть блоків кластерів;
якщо він рівний 1 продовжується робота функції.
Викликаємо функцію ProcessVolume для отримання інформації про сектори диску.
Викликаєм функцію FindFreeBlock для пошуку вільного місця потрібного для переміщення.
переміщаєм файл або директорію за допомогою функції DeviceIoControl з FSCTL_MOVE_FILE.
Закриваємо диск та файл або директорію.
Рис 3.4. Граф-схема алгоритму переміщення блоків кластера
3.3.5. Розробка алгоритму отримання інформації про кластери, запис в які заборонений (void ProcessVolume(HANDLE VolumeName))
Рис 3.5. Граф-схема алгоритму отримання інформації про кластери, запис в які заборонений
Розглянемо алгоритм роботи функції void ProcessVolume(HANDLE VolumeName):
За допомогою функції DeviceIoControl з FSCTL_IS_VOLUME_ MOUNTED перевіряємо чи диск змонтовано:
якщо диск не змонтовано завершуємо роботу з ним;
якщо диск змонтовано продовжуємо роботу з ним.
За допомогою функції DeviceIoControl з FSCTL_GET_VOLUME_ BITMAP отримуєм карту диску:
якщо карту диску не отримано завершуємо роботу з ним;
якщо карту диску отримано продовжуємо роботу з ним.
За допомогою функції DeviceIoControl з FSCTL_GET_NTFS_ VOLUME_ DATA отримуємо інформацію про диск:
якщо інформацію не отримано завершуємо роботу з ним;
якщо інформацію отримано продовжуємо роботу з ним.
Заповнюємо потрібну інформацію.
Загальна схема алгоритму роботи відображена в Додатку 1. Нижче наведені пояснення щодо кожного блоку схеми (номер пункту відповідає номеру блоку на блок-схемі).
Початок.
Початкова ініціалізація утиліти. Входження в функцію main().
Вивід списку логічних дисків.
Виклик системної функції GetLetters.
Перевірка чи знайдено хоча б один логічний диск:
виведення тексу проте, що не знайдено жодного розділу;
виведення інформації про логічні диски і повідомлення про введення символу диску.
Введення символу.
Користувач вводить символ:
Символ відповідає букві логічного диску, перехід до п.4;
Символ відповідає клавіші «Enter», перехід до п.12.
Сканування логічного диску.
Відбувається рекурсивний обхід всіх файлів і директорій логічного диску викликом функцій Dir і GetFiles і для кожного викликається системний виклик GetClusters.
Виведення результату сканування.
Виводиться інформація про те, скільки файлів і директорій було про скановано і скільки з них є фрагментованими.
Введення символу.
Користувач вводить символ:
якщо символ відповідає клавіші «Enter» або фрагментованих файлів не знайдено, перейти до п.2;
якщо символ відповідає клавіші “L”, перейти до п.8;
якщо символ відповідає клавіші “D” перейти до п.7.
Дефрагментація.
Виклик функції Defrag, яка відправляє на дефрагментацію всі знайдені фрагментовані файли і директорії.
Виведення фрагментованих файлів.
Виводить всі файли і директорії, які потребують дефрагментації.
Виведення процесу переміщення кластерів.
В процесі виконання дефрагментації виводиться інформація про те, який файл чи директорія задіяні і інформація які сектори на даний час переміщаються.
Введення символу.
Користувач вводить будь-який символ, перехід до п.6.
Введення символу.
Користувач вводить будь-який символ, перехід до п.2.
Кінець.
Завершення виконання.
4. Інструкція користувача та результати тестування
4.1. Інструкція користувача.
4.1.1. Вимоги для запуску
Вимоги для запуску розробленої системної утиліти для де фрагментації диску:
Утиліта не потребує установки для запуску.
Утиліта вимагає права адміністратора для виконання.
До складу Утиліти входить сам виконавчий модуль: Defrag.exe
Утиліта орієнтована на сімейство операційних систем Windows.
Оскільки програма використовує стандартні WinAPI функції, тому вона не потребує наявності додаткових бібліотек в системі.
4.1.2. Вікно утиліти
Утиліта не має графічного інтерфейсу і виконується у вікні командної стрічки.
Вікно утиліти після запуску (див. Рис. 4.1.). Відображаються всі логічні розділи на комп’ютері і 2 команди для пошуку фрагментованих файлів (з відображенням ходу виконання і без нього).
/
Рис 4.1. Вигляд вікна утиліти після запуску
Для того щоб вибрати диск для пошуку фрагментованих файлів потрібно натиснути клавішу з літерою (в англійській розкладці) для вибору диску (див. Рис. 4.2.) або . клавішу з літерою (в англійській розкладці) + Shift для вибору диску (без відображення проходження процесу сканування) (див. Рис. 4.3.).
/
Рис 4.2. Процес сканування з відображенням
/
Рис 4.3. Процес сканування без відображення
Після сканування виводиться повідомлення про його результати.
знайдено фрагментовані файли і директорії (див. Рис. 4.4.);
якщо натиснути клавішу L буде відображено список фагментованих файлів і директорій (див. Рис. 4.6.);
якщо натиснути клавішу D почнеться дефрагментація (для кожного файлу і директорії відображується які кластери переміщаються або повідомлення про те, що не знайдено місця для переміщення файлу) (див. Рис. 4.7.);
фрагментованих файлів і директорій не знайдено (див. Рис. 4.5.).
/
Рис 4.4. Знайдено фрагментовані файли і директорії
/
Рис 4.5. Фрагментованих файлів і директорій не знайдено
/
Рис 4.6. Список фрагментованих файлів і директорій
/
Рис 4.7. Процес дефрагментації
Для того, щоб повернутись до стартового потрібно натиснути клавішу “ENTER” (якщо не проводиться якась операція).
4.2. Результати тестування
Для тестування проводилась дефрагментація диску F
/
Рис. 4.8. Диск до дефрагментації (Auslogics Disk Defrag)
/
Рис. 4.9. Результати сканування
/
Рис. 4.10. Процес дефрагментації
/
Рис. 4.11. Диск після дефрагментації (Auslogics Disk Defrag)
Висновок
В процесі виконання курсового проекту було розроблено утиліту для дефрагментації логічних розділів жорсткого диску.
Утиліта має такий функціонал:
пошук логічних дисків;
пошук фрагментованих файлів та директорій;
відображення списку фрагментованих файлів та директорій;
дефрагментація фрагментованих файлів та директорій з відображенням процесу де фрагментації.
Утиліта працює в операційних системах сімейства Windows. Розроблена утиліта може використовуватись для дефрагментації, але вона розроблена більше у навчальних і ознайомчих цілях оскільки її функціонал є набагато меншим ніж в інших програм, які виконують аналогічні функції.
У майбутньому можливе розширення функціоналу програми, а саме:
використання графічного інтерфейсу;
можливість дефрагментації з сортуванням;
можливість переміщення файлів для створення великого вільного неперервного блоку.
Список використаних джерел
Джонсон М. Харт, Системное программирование в среде Windows. – М.: Издательский дом «Вильямс», 2005. – 592 с.
Ричард Дж. Саймон, Microsoft Windows 2000 API. Энциклопедия программиста– ДиаСофтЮп, 2002. – 1086 с.
Рихтер Дж., Windows для профессионалов: сохдание эффективных win32-приложений с учетом специфики 64-разрядной версии Windows. – СПб.: Питер, 2008. –720с.
Фрагментація і дефрагментація
http://uk.wikipedia.org/wiki/Фрагментація_і_дефрагментація
Дефрагментаторы http://programy.com.ua/ru/defragmenters/
Inside Windows NT Disk Defragmenting
http://www.windowsitpro.com/article/internals-and-architecture/inside-windows-nt-disk-defragmenting
Додаток 1. Блок-схема алгоритму
Додаток 2. Код програми
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#include<iostream>
#include <list>
#include<locale>
#include <string>
using namespace std;
list<char> GetLetters();
void Search(char let);
void Dir(char *root);
void GetFiles(char* way);
int GetClusters(const char* name,bool d);
void ProcessVolume(HANDLE VolumeName);
int FindFreeBlock(HANDLE VolumeHandle,ULONG64 MinimumLcn,DWORD MinimumSize,ULONG64 *BeginLcn,ULONG64 *EndLcn);
int Defrag();
int files=0;
bool sh=true;
DWORD ClusterSize;
list<string> frag_files;
ULONG64 MaxLcn;
struct {
ULONG64 Start;
ULONG64 End;
} Excludes[3];
void main()
{
setlocale(LC_ALL,"");
while(1)
{
sh=true;
system("cls");
list<char> liss=GetLetters();
if(liss.size()>0)
{
printf("Натиснiть <буква диску> для пошуку фрагментованих файлiв на диску\n"
"Натиснiть Shift+<буква диску> для пошуку без промiжних результатiв\n");
}
else
{
printf("Не знайдено жодного роздiлу\n");
_getch();
return;
}
list<char>::iterator it;
char let=_getch();
if(let==13)
return;
for (it=liss.begin(); it!=liss.end(); ++it)
if(*it==let