вторник, 16 июня 2015 г.

Мини взгляд на работу файловых систем.

Мини взгляд на работу файловых систем.

Файловая система является неотъемлемой частью ос. Основные задачи файловой системы это структурирование каталогов, файлов. Файловая система хранит описатели объектов, где и сколько места занимает файл на физическом диске. Более подробное определение файловой системе дает 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;
}


/* Функция возврата дескриптора директории по имени. Просто проходим по списку в поисках нужной диры, и если все ок, возвращаем дескриптор. */

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();
}

Результат работы :







































Принцип работы вообщем :
//Переход в директорию One
Root\One\
//Переход в директорию Three из One
Root\One\Three\
//Переход (назад) обратно на один уровень
Root\One
//Переход (назад) обратно на один уровень
Root - вернулись откуда начали.

Таблица для подробного вида
Id - идентификатор директории
Pid - идентификатор родителя.
Name - название директории.

Таким образом видно что у директории Root pid = 0, говорит о том что это директория является (корнем).
Директории Three, Two pid = 2, являются поддиректориями One, в свою очередь One является поддиректорией Root.

Name PId Id
Root 0 1
One 1 2
Three 2 3
Two 2 4

Возможные пути Root -> One -> Two Or Three, но нельзя перейти так Root -> Three Or Two минуя One.

Вот так в примитивнейшем случае может выглядеть vfs.

Исходнии

Комментариев нет:

Отправить комментарий