Мини взгляд на работу файловых систем.
Файловая система является
неотъемлемой частью ос. Основные задачи файловой системы это структурирование
каталогов, файлов. Файловая система хранит описатели объектов, где и сколько
места занимает файл на физическом диске. Более подробное определение файловой
системе дает www.wikipedia.ru
:
Файловая
система определяет формат содержимого и способ физического хранения
информации, которую принято группировать в виде файлов. Конкретная файловая система определяет размер имен
файлов и каталогов, максимальный возможный размер файла и раздела,
набор атрибутов файла. В ОС Windows файловая система называется
NTFS. Различные ос, использует разные файловые системы.
Файловые системы обычно можно
представить в виде дерева :
Рис. 2.32. Логическая организация
файловой системы
а - одноуровневая; б - иерархическая
(дерево); в - иерархическая (сеть)
Виртуальная
файловая система.
VFS (Virtual File System) - виртуальная файловая
система, которую я хочу рассмотреть, отличается тем, что работает в оперативной
памяти. Представьте что у вас есть какой сервер который хранит каталоги и файлы
в них, непосредственно в оперативной памяти. Попробуем написать такую fs..
#define
MAX_NAME 255 //Максимальная длина
имени каталога/файла.
#define
INVALIDE_VFS 0 //Признак ошибки
/*
Узел файловой системы */
typedef
struct _VFS_NODE
{
char cbName[MAX_NAME]; //Имя каталога.
_VFS_NODE
*Nodes; //Список узлов
доступных из данной вершины.
_VFS_NODE
*Root; //Узел родительский.,
доступный из данной вершины.
unsigned
long ulParentId; //ID Узла родителя.
unsigned
long ulId; //ID
Непосредственно этого(текущего) узла.
}VFS_NODE,
*PVFS_NODE;
typedef
PVFS_NODE VFSHANDLE;
/*Это
переменная хранит путь.*/
static
std::string g_szCurrentDir = "";
/*
Дескриптор директории */
VFSHANDLE
g_CurrentDirectory = INVALIDE_VFS;
/*Функция
для создания директории
Суть данной функции в следующем : создать
директорию, и возвратить её дескриптор
VFSHANDLE
!= INVALIDE_VFS в случае успеха и
INVALIDE_VFS если наступила неудача., на вход подается szDirName = имя
запрашиваемой.
Остальные необязательные параметры :
PID Родителя * любая директория кроме
корневой должна иметь родителя., по крайне мере в рассматриваемой мной vfs.
ID Непосредственно этой создаваемой
директории.
hRoot - это узел родитель., если есть.
*/
VFSHANDLE
CreateDirectory(const char * szDirName,
unsigned long ulParentId = 0,
unsigned
long ulId = 1,
VFSHANDLE
hRoot = INVALIDE_VFS)
{
if(strlen(szDirName) > MAX_NAME))
return INVALIDE_VFS
;
try
{
PVFS_NODE
lpNode = new VFS_NODE;
strcpy(lpNode->cbName,
szDirName);
lpNode->Nodes = 0;
lpNode->Root = hRoot;
lpNode->ulParentId
= ulParentId;
lpNode->ulId
= ulId;
return
lpNode;
}
catch(...)
{
}
return 0;
}
/*
Данный код создает поддиректорию в директории, на вход дескриптор и имя новой
директории, дескриптор см.Выше создается функцией CreateDirectory
Возврат либо удача, если успешно создана
директория, в текущей директории, иначе ошибка создания.
*/
bool CreateSubDirectory(VFSHANDLE hNode, const char * szSubDirName)
{
if(hNode == INVALIDE_VFS)
return false;
if(strlen(szSubDirName) > MAX_NAME)
return false;
try
{
//это директория будет иметь id = parentID + 1
VFSHANDLE hParent = hNode;
while(hNode->Nodes) hNode = hNode->Nodes; //Ищем свободное место.
//Создаем директорию, передав во первых ID Родителя, новый id, и непосредственно узел родителя.
hNode->Nodes = CreateDirectory(szSubDirName, hParent->ulId, hNode->ulId + 1, hParent);
return hNode->Nodes != INVALIDE_VFS ? true : false;
}
catch(...)
{
}
return false;
}
{
if(hNode == INVALIDE_VFS)
return false;
if(strlen(szSubDirName) > MAX_NAME)
return false;
try
{
//это директория будет иметь id = parentID + 1
VFSHANDLE hParent = hNode;
while(hNode->Nodes) hNode = hNode->Nodes; //Ищем свободное место.
//Создаем директорию, передав во первых ID Родителя, новый id, и непосредственно узел родителя.
hNode->Nodes = CreateDirectory(szSubDirName, hParent->ulId, hNode->ulId + 1, hParent);
return hNode->Nodes != INVALIDE_VFS ? true : false;
}
catch(...)
{
}
return false;
}
/*
Функция возврата дескриптора директории по имени. Просто проходим по списку в
поисках нужной диры, и если все ок, возвращаем дескриптор. */
VFSHANDLE
GetNodeByName(VFSHANDLE hNode, const char * szName)
{
if(hNode ==
INVALIDE_VFS)
return
INVALIDE_VFS;
if(strlen(szName) >
MAX_LEN)
return INVALIDE_VFS;
while(hNode)
{
if(!strcmp(hNode->cbName,
szName))
return
hNode;
hNode =
hNode->Nodes;
}
return INVALIDE_VFS;
}
/* Остальные функции из названия я думаю понятны, что они выполняют */
/* Остальные функции из названия я думаю понятны, что они выполняют */
void
PrintNode(VFSHANDLE hNode)
{
if(hNode ==
INVALIDE_VFS)
return;
printf("Name\tPId\tId\r\n");
while(hNode)
{
printf("%s\t%d\t%d\r\n",
hNode->cbName, hNode->ulParentId, hNode->ulId);
hNode =
hNode->Nodes;
}
}
/
VFSHANDLE GetCurrentDirectory()
{
return
g_CurrentDirectory;
}
void SetCurrentDirectory(VFSHANDLE
hNode)
{
if(hNode ==
INVALIDE_VFS)
return;
if(g_szCurrentDir.length()
<= 0)
{
g_szCurrentDir
+= hNode->cbName;
g_szCurrentDir
+= "\\";
}
g_CurrentDirectory =
hNode;
}
/*Переход
в директорию */
bool GoDirectory(const char *
szPath)
{
VFSHANDLE hRoot =
GetCurrentDirectory();
if(hRoot != INVALIDE_VFS)
{
while(hRoot)
{
if(!strcmp(hRoot->cbName,
szPath))
{
if(GetCurrentDirectory()->ulId
== hRoot->ulParentId)
{
g_szCurrentDir
+= hRoot->cbName;
g_szCurrentDir
+= "\\";
printf("%s\r\n",
g_szCurrentDir.c_str());
return SetCurrentDirectory(hRoot);;
}
}
hRoot
= hRoot->Nodes;
}
}
return false;
}
/*
Возврат на уровень назад */
void GoBack()
{
VFSHANDLE hRoot = GetCurrentDirectory();
if(hRoot != INVALIDE_VFS)
{
if(hRoot->Root != INVALIDE_VFS)
{ std::string::size_type i = g_szCurrentDir.find("\\" + std::string(hRoot->cbName));
if (i != std::string::npos)
g_szCurrentDir.erase(i, g_szCurrentDir.length());
printf("%s\r\n", g_szCurrentDir.c_str());
SetCurrentDirectory(hRoot->Root);
}
}
}
main.cpp
/*
Демонстрация работы VFS
17.06.2015 10:50
(c) vk.com/vtbstr
*/
#include "vfs.h"
#include <stdio.h>
#include <conio.h>
#include <iostream>
using namespace vfs;
#define CODE_EXIT 2
#define CODE_CR 3
#define CODE_CD 4
#define CODE_SHT 5
#define CODE_BK 6
bool StatusOperation(const char * szSrc, bool fStatus)
{
const char * szStatus;
if(fStatus)
szStatus = "OK";
else
szStatus = "FAIL";
printf("%s\t[%s]\r\n", szSrc, szStatus);
return fStatus;
}
int ParseCommand(const char * szBuffer, char * szCommand, char * szArgument)
{
size_t i = 0;
for(i = 0; i < strlen(szBuffer); i++)
{
if(szBuffer[i] == ' ') break;
szCommand[i] = szBuffer[i];
}
int j = 0;
for(++i; i < strlen(szBuffer); i++)
szArgument[j++] = szBuffer[i];
const char * szNormalCommand[] = {"exit", "cr", "cd", "sht", "bk"};
for(size_t i = 0; i < sizeof(szNormalCommand) / sizeof(szNormalCommand[0]); i++)
{
if(!_stricmp(szNormalCommand[i], szCommand))
return i + 2;
}
return 0;
}
int main()
{
char cbBuff[MAX_NAME] = {0};
printf("Enter Root Directory Name\r\n");
std::cin.getline(cbBuff, MAX_NAME - 1);
StatusOperation("Install Current Directory : ", SetCurrentDirectory(CreateDirectory(cbBuff)));
printf("If you want Exit programm enter : exit\r\n");
printf("If you want Create Directory enter : cr [Directory Name]\r\n");
printf("If you want Change current Directory enter : cd [Directory Name]\r\n");
printf("Show All Nodes tree enter : sht\r\n");
printf("If you want Go Back enter : bk\r\n");
printf("Good Luck!\r\n");
printf("VFS Simulation By I.D (c) vtbstr all right reserved\r\n");
printf("contact : vk.com/vtbstr\r\n");
while(1)
{
char szCommand[MAX_NAME] = {0};
char arg[MAX_NAME] = {0};
std::cin.getline(cbBuff, MAX_NAME - 1);
int nCode = ParseCommand(cbBuff, szCommand, arg);
StatusOperation("Parse Command...", nCode);
if(nCode)
{
if(nCode == CODE_EXIT)
{
printf("Unload Programm!\r\n");
break;
}
else if(nCode == CODE_CR)
StatusOperation("Create SubDirectory...", CreateSubDirectory(GetCurrentDirectory(), arg));
else if(nCode == CODE_CD)
StatusOperation("CD To Directory...", GoDirectory(arg));
else if(nCode == CODE_BK)
StatusOperation("Back Directory...", GoBack());
else if(nCode == CODE_SHT)
PrintNode(GetCurrentDirectory());
}
}
printf("Press any key!\r\n");
return _getch();
}
#include <stdio.h>
#include <conio.h>
#include <iostream>
using namespace vfs;
#define CODE_EXIT 2
#define CODE_CR 3
#define CODE_CD 4
#define CODE_SHT 5
#define CODE_BK 6
bool StatusOperation(const char * szSrc, bool fStatus)
{
const char * szStatus;
if(fStatus)
szStatus = "OK";
else
szStatus = "FAIL";
printf("%s\t[%s]\r\n", szSrc, szStatus);
return fStatus;
}
int ParseCommand(const char * szBuffer, char * szCommand, char * szArgument)
{
size_t i = 0;
for(i = 0; i < strlen(szBuffer); i++)
{
if(szBuffer[i] == ' ') break;
szCommand[i] = szBuffer[i];
}
int j = 0;
for(++i; i < strlen(szBuffer); i++)
szArgument[j++] = szBuffer[i];
const char * szNormalCommand[] = {"exit", "cr", "cd", "sht", "bk"};
for(size_t i = 0; i < sizeof(szNormalCommand) / sizeof(szNormalCommand[0]); i++)
{
if(!_stricmp(szNormalCommand[i], szCommand))
return i + 2;
}
return 0;
}
int main()
{
char cbBuff[MAX_NAME] = {0};
printf("Enter Root Directory Name\r\n");
std::cin.getline(cbBuff, MAX_NAME - 1);
StatusOperation("Install Current Directory : ", SetCurrentDirectory(CreateDirectory(cbBuff)));
printf("If you want Exit programm enter : exit\r\n");
printf("If you want Create Directory enter : cr [Directory Name]\r\n");
printf("If you want Change current Directory enter : cd [Directory Name]\r\n");
printf("Show All Nodes tree enter : sht\r\n");
printf("If you want Go Back enter : bk\r\n");
printf("Good Luck!\r\n");
printf("VFS Simulation By I.D (c) vtbstr all right reserved\r\n");
printf("contact : vk.com/vtbstr\r\n");
while(1)
{
char szCommand[MAX_NAME] = {0};
char arg[MAX_NAME] = {0};
std::cin.getline(cbBuff, MAX_NAME - 1);
int nCode = ParseCommand(cbBuff, szCommand, arg);
StatusOperation("Parse Command...", nCode);
if(nCode)
{
if(nCode == CODE_EXIT)
{
printf("Unload Programm!\r\n");
break;
}
else if(nCode == CODE_CR)
StatusOperation("Create SubDirectory...", CreateSubDirectory(GetCurrentDirectory(), arg));
else if(nCode == CODE_CD)
StatusOperation("CD To Directory...", GoDirectory(arg));
else if(nCode == CODE_BK)
StatusOperation("Back Directory...", GoBack());
else if(nCode == CODE_SHT)
PrintNode(GetCurrentDirectory());
}
}
printf("Press any key!\r\n");
return _getch();
}
Принцип работы вообщем :
//Переход в директорию One
Root\One\
//Переход в директорию Three из One
Root\One\Three\
//Переход (назад) обратно на один уровень
Root\One
//Переход (назад) обратно на один уровень
Root - вернулись откуда начали.
Таблица для подробного вида
Id - идентификатор директории
Pid - идентификатор родителя.
Name - название директории.
Таким образом видно что у директории Root pid = 0, говорит о том что это директория является (корнем).
Директории Three, Two pid = 2, являются поддиректориями One, в свою очередь One является поддиректорией Root.
Root 0 1
One 1 2
Three 2 3
Two 2 4
Возможные пути Root -> One -> Two Or Three, но нельзя перейти так Root -> Three Or Two минуя One.
Вот так в примитивнейшем случае может выглядеть vfs.
Исходнии
Комментариев нет:
Отправить комментарий