Zpět na seznam článků     Číst komentáře (70)     Verze pro tisk

Tvoříme OS [4.díl]

Autor: DjH   
18.9.2008

V tomhle díle si pokusíme vypsat obsah nějakého souboru na disku...


Tvoříme OS

Díl 4

V tomto díle se pokusíme přijít na to, jak vypsat takový obsah souboru. Jak vyhledat soubor již víme, vypsání je o něco složitější. Až přijdeme na to, jak takový soubor vypsat, můžeme pak jednoduše vytvořit funkce jako fopen(), fread(), fclose()...
   Pro náš OS jsme vybrali disketu, a jako FS zvolili FAT12. Tam jsou soubory uložené v tzv. File Allocation Table, tedy FAT tabulce. Na 1.44 MB disketě je FAT velká 9 sektorů (+ jedna záložní FAT, tedy dohromady 18 sektorů), počínaje druhým sektorem, tedy hned za bootloaderem. V tabulce je uložené číslo clusteru, na které nějaký soubor začíná, kde pokračuje, a kde končí popř. že např. následující cluster je poškozený.
   Jelikož jsou tyto údaje 12tibitové a C nemá 12tibitový datový typ, vytvoříme si speciální cyklus, pomocí kterého vypíšeme obsah souboru.

Jak to tedy bude pracovat...
Vytvoříme si novou globální proměnnou „fat“. Zde bude celá FAT tabulka, a do funkce init() se přidá načtení FAT do proměnné. K samotnému vypsání: nejdříve se (prozatím) v rootové složce najde soubor. Každý soubor má v atributech počáteční číslo klastru, na kterém začíná. Toto číslo se předá do cyklu, který sektor po sektoru vypíše obsah, dokud nenarazí ve FAT tabulce na konec souboru. Stále vás napínám s „cyklem“, tak vám ho ukážu:
  1.  
  2.   <b>while</b>(1) {
  3.     readdisk((StartSector + (cluster - 2)), 1, dummy);
  4.     dummy[513] = '\0';
  5.     printf("%s", dummy);
  6.     cluster = *((<b>unsigned int</b>*)(fat+((cluster * 3) / 2)));
  7.     <b>if</b> (t & 1) cluster &gt;&gt;= 4;
  8.     <b>else</b> cluster &= 0x0fff;
  9.     <b>if</b> (fat_end(cluster)) <b>break</b>;
  10.     t = cluster;
  11.   }
  12.  

Teď trochu upřesním co se děje:
Nejdřív se načte prvních 512 bajtů (1 sektor) do proměnné dummy, dále se přidá na konec (513tý bajt) \x00, aby zakončil případný string, dále se vypíšou načtené bajty z proměnné dummy, poté se zjistí číslo příštího klastru, pokud je klastr lichý, posune se číslo příštího klastru o 4 bity doprava, pokud je klastr sudý, ořízne se na 3 bity ("vyANDováním" 0xFFF), zkontroluje se, jestli není příští klastr poškozený nebo jestli není konec souboru. Pokud je, skončí cyklus, a pokud není, za „t“ se dosadí číslo klastru a cyklus se opakuje do té doby, dokud cyklus nenarazí na konec souboru.
   Minule jsme si vytvořili funkci findfile() která nám najde soubor a vrátí -1 když ho nenajde. Nyní si vytvoříme funkci catfile(char *file), která nám vypíše obsah souboru <file> na monitor. Proběhne to asi takhle:
Asociujeme různé proměnné, jako třeba StartSector a alokujeme paměť pro buffer, kam se budou nahrávat data. Poté smyčkou findfile() najdeme soubor, jestli bude nalezen, předáme hodnotu prvního klastru do proměnné cluster a skočíme do výše uvedeného cyklu. Ten postupně vypíše obsah celého souboru, po jeho skončení se dealokují proměnné a opustí se funkce. V reálu bude funkce vypadat asi takto:
  1.  
  2. <b>int</b> catfile(<b>char</b> *filename) {
  3.   <b>unsigned int</b> StartSector = (DataStart+1);
  4.   <b>unsigned int</b>; <i>/*= cluster;*/</i>
  5.   <b>unsigned int</b> cluster; <i>/*= cluster;*/</i>
  6.   <b>int</b> i=0;
  7.   <b>char</b> *dummy = (<b>char</b>*)malloc(512);
  8.   DirectoryEntry *file = malloc(<b>sizeof</b>(DirectoryEntry));
  9.  
  10.   <b>while</b>((i = findfile(file, i)) != -1) {
  11.     <b>if</b>(!strcmp(file-&gt;realname, filename)) {
  12.       <b>if</b>(file-&gt;attr == 0x20) {
  13.         cluster = file-&gt;ClstrNo;
  14.         t = cluster;
  15.         <b>goto</b> vypis;
  16.       }
  17.     }
  18.   }  
  19.   free(dummy);
  20.   free(file);
  21.   printf(<u>"Soubor '%s' nebyl nalezen!\r\n"</u>, filename);
  22.   <b>return</b> 1;
  23.  
  24.   vypis:
  25.   <b>while</b>(1) {
  26.     readdisk((StartSector + (cluster - 2)), 1, dummy);
  27.     dummy[513] = '\0';
  28.     printf("%s", dummy);
  29.     cluster = *((<b>unsigned int</b>*)(fat+((cluster * 3) / 2)));;
  30.     <b>if</b> (t & 1) cluster &gt;&gt;= 4;
  31.     <b>else</b> cluster &= 0x0fff;
  32.     <b>if</b> (fat_end(cluster)) <b>break</b>;
  33.     t = cluster;
  34.   }
  35.   free(dummy);
  36.   free(file);
  37.   <b>return</b> 0;
  38. }
  39.  

Nyní, když zavoláte tuto funkci a jako vstupní string zadáte název nějakého souboru, funkce vypíše na monitor jeho obsah. Pokud soubor neexistuje, vypíše chybovou hlášku. Dávejte si pozor a uvědomte si, že soubory ve FAT12 se píší velkými písmeny, tedy pokud je na disku soubor „soubor.txt“, musíte zavolat funkci takto >
catfile("SOUBOR.TXT");, tedy catfile("soubor.txt"); vypíše chybovou hlášku, že soubor neexistuje... Pokud chcete přidat možnost, že se string převede na velká písmena, není problém, v hlavičce string.h je funkce upStr(), ale toto už nechám na vás :).
Ještě mírně upravím kernel.c tak, aby čekal na vstup od uživatele, po stisku enteru zkusí najít uvedený soubor na disku a vypíše jeho obsah (v opačném případě chybovou hlášku, že nebyl soubor nalezen).
  1.  
  2. <b>int</b> main(<b>void</b>) {
  3. <b>char</b>            cmd[80];
  4.   init();
  5.   <b>while</b>(1) {
  6.     printf(<u>"[%s@%s]%s$ "</u>, user_name, pc_name, path);
  7.     gets(cmd, 79);
  8.     catfile(cmd);
  9.   }
  10.   <b>return</b> 0;
  11. }
  12.  

   Myslím si, že dnešní díl nebyl zase tak složitý jak by se mohlo zprvu zdát. Příští díl bych chtěl ukázat, jak funguje spouštění aplikací, tedy, zkusíme si spustit naši první externí aplikaci. Na závěr přikládám screenshot:
  1.  
  2.  


archív zde

Všechny díly seriálu

Tvoříme OS [1.díl]
Tvoříme OS [2.díl]
Tvoříme OS [3.díl]
Tvoříme OS [4.díl]
Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 2.62/170

1  2  3  4  5    
(známkování jako ve škole)