]> rtime.felk.cvut.cz Git - mf6xx.git/commitdiff
Diploma thesis text.
authorRostislav Lisovy <lisovy@gmail.com>
Fri, 22 Apr 2011 15:08:27 +0000 (17:08 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Fri, 22 Apr 2011 15:08:27 +0000 (17:08 +0200)
doc/diploma_thesis/text/dip_text.tex

index 4fde3a9fd60bfa0a9006ff15c399cf67d8d98f6b..8ec5bc6766b2d5117f5b71e7e7d06d3f8b1d3ebc 100644 (file)
@@ -569,7 +569,7 @@ První sloupec označuje adresu začátku regionu, druhý jeho konec. Třetí sl
 
 
 
-\subsection{Základní jaderný modul}
+\subsection{Základní jaderný modul}\label{kern_mod}
 Jádro operačního systému GNU/Linux je monolitické -- to znamená, že po zkompilování a slinkování je tvořeno jedním kusem kódu. Tento druh jádra je léty prověřen a mezi výhody patří jeho snadná implementace. Aby běžící jádro nemuselo obsahovat veškeré dostupné ovladače zařízení (nebo abychom v případě potřeby přidat do jádra ovladač pro nový hardware nemuseli celé jádro znovu kompilovat), existuje mechanismus načítání jaderných modulů za běhu, tzv. LKM -- Loadable Kernel Module. V praxi to vypadá tak, že jsou v běžícím jádře zakompilovány pouze nejnutnější ovladače, všechny ostatní si může systém nebo uživatel za běhu do jádra načíst -- v případě, že již nejsou potřeba, je možné je z jádra uvolnit.
 
 Jak se takový jaderný modul může vypadat, je nejlepší si ukázat na příkladu:
@@ -599,7 +599,7 @@ Z příkladu je patrné, že je modul napsán v programovacím jazyce C. To plat
 \item[Řádky 1 a 2] obsahují vložení hlavičkových souborů -- obsahují prototypy volaných funkcí a jsou nutné pro tvorbu jaderného modulu.
 \item[Na řádcích 4--8] je funkce, která bude spuštěna ihned po zavedení našeho modulu do jádra. Ta obsahuje pouze volání funkce \texttt{printk()}.
 
-Pro jednoduchost můžeme s funkcí \texttt{printk()} pracovat jako s, pro čtenáře známou, funkcí \texttt{printf()} -- na rozdíl od standardního výstupu se však text vypsaný funkcí \texttt{printk()} zapíše do \textit{logu} jádra. Jedním ze způsobů, jak ho zobrazit je pomocí programu \texttt{dmesg}.\\Jak se zařídí, že se tato funkce vykoná ihned po zavedení modulu do jádra? O to se postará příkaz na $\rightarrow$
+Pro jednoduchost je možné s funkcí \texttt{printk()} pracovat jako s, jistě známou, funkcí \texttt{printf()} dostupnou v uživatelském prostoru -- na rozdíl od standardního výstupu se však text vypsaný funkcí \texttt{printk()} zapíše do \textit{logu} jádra. Jedním ze způsobů, jak ho zobrazit je pomocí programu \texttt{dmesg}.\\O to, že se tato funkce vykoná ihned po zavedení modulu do jádra, se postará příkaz na $\rightarrow$
 \item[řádku 15] -- ten obsahuje makro \texttt{module\_init()}, kterému řekneme právě to, která funkce se má po načtení spustit.
 \item[Řádek 16] obsahuje naopak makro, které udává, která funkce se má zavolat v případě, že se bude modul uvolňovat z jádra. V našem případě je to funkce na $\rightarrow$
 \item[řádcích 10--13.] Tato funkce nemá na starost nic jiného než výpis krátkého textu do logu jádra.
@@ -655,9 +655,9 @@ V případě, že vše proběhlo správně, měl by být v logu jádra text vypi
 $ dmesg | tail -1
 [ 9245.757491] Hello, world!
 \end{verbatim}
-A skutečně je posledním řádkem v logu text vypsaný zavedeným modulem.
+A skutečně je posledním řádkem v logu text vypsaný úspěšně zavedeným modulem.
 
-Pro plné otestování funkčnosti ukázkového modulu, je potřeba ho z jádra uvolnit. K tomu slouží program \texttt{rmmod} (opět je potřeba spouštět se superuživatelskými privilegii).
+Pro plné otestování funkčnosti ukázkového modulu, je potřeba ho ještě z jádra uvolnit. K tomu slouží program \texttt{rmmod} (opět je potřeba spouštět se superuživatelskými privilegii).
 \begin{verbatim}
 $ sudo rmmod hello 
 
@@ -667,7 +667,7 @@ $ dmesg | tail -1
 V logu je opět nachází text vypisovaný modulem při uvolňování z jádra.
 
 
-\ibox{V případě, že se chystáme do jádra zavést modul, jehož jsme autoři a nejsme si jisti jeho funkčností, doporučuji si veškerou důležitou práci uložit a před zavedením/uvolněním modulu do/z jádra spustit program \texttt{sync}, který uloží obsah diskových bufferů na disky.}
+\ibox{V případě, že má být do jádra zaveden modul, jehož funkčnost a stabilita není jistá, je vhodné si uložit veškerou práci a před zavedením/uvolněním modulu do/z jádra spustit program \texttt{sync}, který uloží obsah diskových bufferů na disky.}
 
 \subsection{Na co si dávat pozor}
 Při psaní základního modulu pro jádro Linux nejsou patrné větší rozdíly oproti psaní programů pro uživatelský prostor. I přesto, že tyto rozdíly nejsou vidět, stále tady jsou. Mezi ty nejdůležitější, kterých si má být programátor vědom, patří:
@@ -714,10 +714,60 @@ Za pomoci volání \texttt{goto} je výše popsaný problém elegantně vyřeše
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \section{Základní funkce v prostředí jádra Linux}
-\subsection{Funkce \texttt{printk()}}
-FIXME
-\subsection{Funkce \texttt{kalloc()}}
+V jádře Linux je kromě funkcí specifických pro práci se zařízením určitého typu, také sada obecných funkcí používaných napříč všemi ovladači. Mezi ně patří například funkce pro vypisování ladících zpráv, funkce pro alokaci a uvolňování paměti.
+
+\subsection{Funkce \texttt{printk()} pro vypisování ladících zpráv}
+\ibox{\texttt{printk(FIXME)};}
+V kapitole \ref{kern_mod} již byla zmíněna funkce \texttt{printk()} v základní verzi, přirovnaná k funkci \texttt{printf()} z uživatelského prostoru. Kromě \textit{obyčejného} vypisování textu do logu jádra podporuje tato funkce navíc nastavení úrovně důležitosti zprávy a speciální formátovací řetězce.
+
+Nastavení úrovně důležitosti zprávy se provede vložením \textit{nastavovacího} makra \textbf{před} samotný řetězec obklopený uvozovkami. Možné druhy zpráv jsou (od nejkritičtější po nejméně důležitou):
+\begin{description}
+\item[\texttt{KERN\_EMERG}]~\\Zpráva nejvyšší úrovně. Většinou předchází neodvratnému pádu jádra.
+\item[\texttt{KERN\_ERR}]~\\Informace o vzniklé chybě. Bývá použito např. při informování o špatné funkci hardware.
+\item[\texttt{KERN\_WARNING}]~\\Upozornění o nezávažné chybě.
+\item[\texttt{KERN\_INFO}]~\\Informační zpráva. Může být použito např. od ovladače zařízení o úspěšném spuštění.
+\item[\texttt{KERN\_DEBUG}]~\\Obyčejná ladící zpráva.
+\end{description}
+
+\vspace{5mm}
+
+Formátovací řetězce fungují podobně jako u funkce \texttt{printf()}. Kromě známých, \texttt{\%s}, \texttt{\%u}, \texttt{\%d} a \texttt{\%x} jsou zde navíc:
+
+\begin{description}
+\item[\texttt{\%p}] Slouží k výpisu hodnoty ukazatele.
+\item[FIXME]
+\end{description}
+
+Příklad nastavení typu zprávy a použití formátovacího řetězce:
+\begin{verbatim}
+    printk(KERN_DEBUG "I'm trashed; giving up on %p\n", ptr);
+\end{verbatim}
+
+
+\subsection{Funkce \texttt{kmalloc()}, \texttt{kzalloc()} pro alokaci paměti}
+Problematika alokace paměti v prostředí jádra Linux je velice rozsáhlá. Pomocí speciálních funkcí je možné alokovat celé paměťové stránky nebo FIXME velkou oblast ve virtuálním paměťovém prostoru.
+
+\ibox{\texttt{void *kmalloc(size\_t size, int flags);}}
+Základní funkce pro alokaci malé paměťové oblasti (např. pro strukturu obsahující privátní data ovladače) je \texttt{kmalloc()}. Prvním parametrem je velikost alokované paměti (maximálně však 128 KB (FIXME)), druhým je příznak určující o jaký druh alokace se jedná. Nejuniverzálnější možností je \texttt{GFP\_KERNEL}.
+
+Příklad alokace a uvolnění paměti (včetně ošetření chybových stavů):
+\begin{verbatim}
+  1 |  struct uio_info *info;
+  2 |  info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+  3 |  if (!info) {
+  4 |      return -ENOMEM;
+  5 |  }
+  6 |  /* práce s pamětí */
+  7 |                  
+  8 |  kfree(info);
+\end{verbatim}
+
+
 \subsection{Funkce \texttt{kfree()}}
+\ibox{\texttt{void kfree(void *obj);}}
+
+Když již alokovaná paměť není potřeba, je nutné ji voláním \texttt{kfree()} uvolnit. 
+
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \section{Ovladače PCI zařízení}\label{pci_driv}
@@ -1056,7 +1106,7 @@ mf624_BAR2 += (BAR2_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
 Jelikož se jedná o paměť zařízení, je potřeba i v uživatelském prostoru k této paměti přistupovat pomocí speciálních funkcí. Ty jsou popsány v kapitole \ref{iofce}.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\newpage
+%\newpage
 \section{Comedi ovladač}
 Kromě popsaných výhod UIO ovladače jsou zde i nevýhody. Jednou z nich je pomalejší odezva než v případě plnohodnotného jaderného ovladače. Další nevýhodou je neexistence knihovny v uživatelském prostoru, která by poskytovala jednotné API pro přístup k zařízení (v případě UIO ovladače je potřeba vytvořit pro každé zařízení specifický program).
 
@@ -1128,8 +1178,27 @@ Alokace paměti pro struktury se provede voláním \texttt{alloc\_subdevices()},
 V případě dealokace zdrojů ovladače není potřeba tuto paměť dealokovat -- o uvolnění paměti se postará Comedi subsystém. 
 
 \subsection{Funkce pro čtení a zápis z/do podzařízení}
+Funkce pro čtení, zápis a konfiguraci A/D, D/A převodníků a digitálních vstupů a výstupů mají stejné parametry. Jsou to: \texttt{(struct comedi\_device *dev, 
+struct comedi\_sub- device *s, struct comedi\_insn *insn, unsigned int *data)};
+
+V prvním parametru je předán ukazatel na strukturu reprezentující Comedi zařízení. Díky tomu je možné prostřednictvím její proměnné \texttt{private} získat ukazatel na strukturu obsahující privátní data ovladače.
+
+Druhý parametr je ukazatel na strukturu reprezentující podzařízení. Tato struktura obsahuje, kromě položek inicializovaných ve funkci \textit{attach} i proměnnou \texttt{state}. Tato proměnná popisuje \textit{stav zařízení} a používá se především pro zjištění stavu digitálních výstupů (stav digitálních výstupů není možné za zařízení přečíst, pro změnu pouze jednoho bitu je tedy potřeba znát stav ostatních).
+
+Třetí parametr obsahuje ukazatel na strukturu popisující danou \textit{instrukci}, která má být provedena. Důležité položky, které tato struktura obsahuje:
+\begin{description}
+\item[\texttt{unsigned int n}]~\\Udává počet instrukcí, které mají být provedeny
+\item[\texttt{unsigned int chanspec}]~\\Obsahuje informace o kanálu podzařízení, na kterém má být operace provedena. V jedné proměnné typu \texttt{unsigned int} je obsaženo více údajů, proto je potřeba ke čtení používat speciální makro
+\texttt{CR\_CHAN()}, které vrací číslo zvoleného kanálu.
+\end{description}
+
 
 \subsection{Funkce \texttt{detach}}
+Tato funkce je volána jak v případě ukončení funkce ovladače, tak v případě, že funkce \textit{attach} neproběhla v pořádku. Proto je potřeba rozlišit, které zdroje ovladače již byly úspěšně naalokovány a mají být uvolněny.
+
+Odregistrování ovladače z PCI a Comedi subsystému by mělo být voláno v \textit{úklidové funkci} modulu. O samotné odregistrování se starají funkce:
+\texttt{pci\_unregister\_driver()} a \texttt{comedi\_driver\_unregister()}, kterým se jako parametr předá ukazatel na strukturu použitou při registraci.
+
 
 \subsection{Přístup z uživatelského prostoru}
 Pro správnou funkci konkrétního Comedi ovladače je nejprve potřeba načíst modul Comedi (\texttt{modprobe comedi}). Poté je již možné načíst ovladač zařízení (v případě ručně kompilovaného ovladače, pomocí příkazu \texttt{insmod}, jinak opět pomocí \texttt{modprobe}).