[Kos-cvs] kos/doc Makefile, 1.28, 1.29 helloworld-screenshot.png, NONE, 1.1 helloworld.tex, NONE, 1.1

thomas at kos.enix.org thomas at kos.enix.org
Sun Jan 16 00:07:43 CET 2005

Update of /home/kos/cvs/kos/doc
In directory the-doors:/tmp/cvs-serv29895

Modified Files:
Makefile
helloworld-screenshot.png helloworld.tex
Log Message:
Ajout de la documentation sur la création d'un module Hello World.

--- NEW FILE: helloworld-screenshot.png ---
(This appears to be a binary file; contents omitted.)

Index: Makefile
===================================================================
RCS file: /home/kos/cvs/kos/doc/Makefile,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- Makefile	9 Jan 2005 16:05:59 -0000	1.28
+++ Makefile	15 Jan 2005 23:07:41 -0000	1.29
@@ -20,7 +20,7 @@
modules.dvi: module.eps
testingfr.dvi: screenshot-qemu.eps screenshot-terminal.eps
testingen.dvi: screenshot-qemu.eps screenshot-terminal.eps
-
+helloworld.dvi: helloworld-screenshot.eps

DEP_CLEAN=html-clean doxygen-clean

--- NEW FILE: helloworld.tex ---
\documentclass[11pt, a4paper, oneside, openany]{article}

%% \usepackage[frenchb]{babel}
\usepackage[latin1]{inputenc}
\usepackage{graphicx}
\usepackage{palatino}
\usepackage{a4wide}
\usepackage{verbatim}
\usepackage{relsize}
\usepackage{listings}
\usepackage{float}
\usepackage{listings}

\floatplacement{figure}{H}

\lstset{language=C,frame=Ltbr,basicstyle=\ttfamily}

\usepackage[dvips,
pdftitle={The Hello World in KOS},
pdfauthor={KOS Team},
pdfsubject={Write your first KOS, coding conventions},
pdfpagemode={UseOutlines},
bookmarks=true,
urlcolor={red},
citecolor={green},
urlbordercolor={0 0 1},
citebordercolor={1 0 0}
]{hyperref}

%BEGIN IMAGE
\newlength{\taillecol}
%HEVEA \setlength{\taillecol}{11cm}
%END IMAGE
%BEGIN LATEX
%BEGIN LATEX
\newcommand{\mysub}[3]{\subfigure[#2]{#3}}
\setlength{\taillecol}{\linewidth}
%END LATEX

%% \newcommand{\mailto}[1]{\href{mailto:#1}{\tt #1}}
\newcommand{\mailto}[1]{{\tt #1}} %% Pas de href dans les footnotes
%% sur kos.enix.org (pb latex)

\newcommand{\kos}{{\sc Kos}}
\newcommand{\ie}{{\em i.e.\/}\ }

\title{First KOS module and coding conventions}
\author{Thomas Petazzoni\footnote{\mailto{thomas.petazzoni at enix.org}}}
\date{15 Janvier 2005}

\begin{document}
\maketitle

\begin{abstract}
This documents explains how to create a simple, {\em Hello World}
type, module in \kos, and give some recommandations regarding coding
conventions.
\end{abstract}

\tableofcontents

\section{Location}

All modules in \kos~are stored in the {\tt modules/} directory, or in
one of its subdirectories. The most important subdirectories are {\tt
x86/}, the directory that contains x86-specific code, {\tt lib/}, the
directory that contains various libraries and {\tt fs/}, the directory
that contains filesystems implementation.

So, to create the {\em Hello World} module, simply create a {\tt
helloworld/} subdirectory inside {\tt modules/}.

\section{Initialisation and cleanup routines}

Each module may have one or more initialisation or cleanup
routines. Currently, only initialisation routines are useful, since
\kos~is not able to unload modules.

Initialisation and cleanup routines are usually written in a C file
that has the name of the module, in our case, it will be {\tt
helloworld.c}. This file should contain nothing except initialisation
and cleanup routines, and symbol export directives (see
\ref{export-symbols}).

There are two kinds of initialisation routines :

\begin{itemize}

\item {\tt init} routines, that are called before the interrupts are
enabled in the operating system. There should be used only for the
low-level modules like memory or task management;

\item {\tt post init} routines, called once the interrupts are
enabled and the system is running threads;

\end{itemize}

For each type of initialisation routines, there are different
levels that allows to order the initialisation of the various
modules. All initialisation routines of level 0 are called before
initialisation routines of level 1, etc. There are both initialisation
levels for {\tt init} and {\tt post init} initialisation
routines. Inside an initialisation level, the call order is defined by
the order of the modules in the {\tt MkVars} file (see
\ref{compilation}).

As our {\em Hello World} module doesn't contain any low-level feature,
we'll only use a {\tt post init} initialisation routine, that we'll
put at level 0 ;

\begin{lstlisting}[caption=Initialisation routine]
__init_text static int post_init_module_level0
(kernel_parameter_t *kp)
{
UNUSED(kp);

printk("(Init module helloworld... Ok)");
return 0;
}
\end{lstlisting}

The {\tt post init} routines are usually named {\tt
post\_init\_module\_level} appended with the level at which the
routine will be executed. The {\tt kernel\_paramater\_t} argument is
passed to all modules, it contains various information concerning the
configuration set up by the {\em loader}. These information are only
useful for some modules.

The {\tt \_\_init\_text} statement allows the kernel to frees the
memory used by the initialisation code once initialisation is
done. All global variables or functions used only during
initialisation should use this statement. The {\tt static} statement
ensures that the function is not used anywhere outside of the current
file.

The {\tt UNUSED} macro is a simple macro that allows to avoid warnings
about unused arguments. We activated a lot of warnings, including the
ones about unused arguments. If you really know that you don't want to
use an argument, mark it with {\tt UNUSED}. {\tt UNUSED} must be
placed after all local variables declaration.

Now, we have to register this function as an initialisation routine,
using the following statement :

\begin{lstlisting}[caption=Initialisation routine declaration]
DECLARE_INIT_SYMBOL(post_init_module_level0, POST_INIT_LEVEL0);
\end{lstlisting}

That's enough to define an initialisation routine. We should also
include {\tt loader/mod.h} that contains the definitions for the
macros used to declare initialisation routines, {\tt lib/std/libstd.h}
that contains the definition of the {\tt printk} function and {\tt
kos/macros.h} that contains the definition of the {\tt UNUSED}
macro.

\begin{lstlisting}[caption={\tt helloworld.c} source code]
#include <kos/macros.h>
#include <lib/std/stdlib.h>

__init_text static int post_init_module_level0
(kernel_parameter_t *kp)
{
UNUSED(kp);

printk("(Init module helloworld... Ok)");
return 0;
}

DECLARE_INIT_SYMBOL(post_init_module_level0, POST_INIT_LEVEL0);
\end{lstlisting}

\section{Compilation}
\label{compilation}

In order to compile our module, we need to set up a simple {\tt
Makefile}, in the module directory :

\begin{lstlisting}[caption={\tt Makefile} for the {\em Hello World} module]
OBJS=  helloworld.o

all: helloworld.ro

helloworld.ro: $(OBJS) TOPSRCDIR=../.. include$(TOPSRCDIR)/modules/MkRules
\end{lstlisting}

The {\tt OBJS} variables must contain the name of all object files
that must be compiled in the module. {\tt helloworld.ro} is the result
of the compilation : it is the module itself, usable by the
loader. Using that {\tt Makefile}, you can now compile your module by
simply typing {\tt make}.

However, if you recompile \kos~completely, your module won't be
compiled. To do this, simply add {\tt helloworld} inside the {\tt
SUBDIRS} variable at the top of the {\tt modules/Makefile} file.

Now that your module is compiled, it has to be added to the floppy
image of the operating system with the other modules. To do this, you
have to edit the {\tt MkVars} file at the main directory of
\kos~sources, and add the following line to the {\tt MODULES} variable
:

{\relsize{-2}\begin{verbatim}
$(MODULES_DIR)/helloworld/helloworld.ro \end{verbatim} } %$

given in the {\em Compile, test and debug \kos} documentation. You
should see the string printed through {\tt printk} after the \kos
logo. The figure \ref{fig:screenshot} shows what you should see. The red
color of the message has been added afterwards, you should see it with
the normal grey color.

\begin{figure}[htbp]
\centering \includegraphics[width=\taillecol]{helloworld-screenshot.eps}
\caption{{\em Hello World} module running}
\label{fig:screenshot}
\end{figure}

\section{Module functionalities, exporting symbols}

Your {\em Hello World} module is very simple for the moment. Let's add
some functionalities to it. The first one is an internal function of
the module, which can be called only inside the module. This function
will be called {\tt hello\_inside}. The second one is a function which
is going to be exported, which means that other modules will be able
to call it.

All module functionalities should be implemented in C source files
whose names start with an underscore. In our example, the code will be
stored inside the {\tt \_helloworld.c} file.

\begin{lstlisting}[caption=The code of the {\em Hello World} module]
#include <lib/std/stdlib.h>

void hello_inside(void)
{
printk(Hello from the inside'');
}

void hello_outside(void)
{
printk(Hello from the outside'');
}
\end{lstlisting}

Now, we have to declare the prototypes of these functions in header
files. The prototypes of exported functions and all public information
(type definitions, macro definitions) must be placed in a header that
has the name of the module, in our case {\tt helloworld.h}. Other
modules are allowed to include such a file.

\begin{lstlisting}[caption=Public include file {\tt helloworld.h}]
#ifndef __HELLOWORLD_H__
#define __HELLOWORLD_H__

void hello_outside();

#endif /* __HELLOWORLD_H__ */
\end{lstlisting}

The private function prototypes, type and macro definitions should be
placed in a header file called {\tt \_helloworld.h}. It should not be
included by other modules, but has to be included by the files of the
{\tt helloworld} module. It should contains a directive to include the
public file {\tt helloworld.h}.

\begin{lstlisting}[caption=Private include file {\tt \_helloworld.h}]
#ifndef ___HELLOWORLD_H__
#define ___HELLOWORLD_H__

#include _helloworld.h''

void hello_inside();

#endif /* ___HELLOWORLD_H__ */
\end{lstlisting}

Now, we can modify the {\tt helloworld.c} file to use the {\tt
hello\_inside} function and to export the {\tt hello\_outside}
function :

\begin{lstlisting}[caption={\tt helloworld.c} source code]
#include <kos/macros.h>
#include <lib/std/stdlib.h>
#include _helloworld.h''

__init_text static int post_init_module_level0
(kernel_parameter_t *kp)
{
UNUSED(kp);

printk("(Init module helloworld... Ok)");
hello_inside();
return 0;
}

EXPORT_FUNCTION(hello_outside);
DECLARE_INIT_SYMBOL(post_init_module_level0, POST_INIT_LEVEL0);
\end{lstlisting}

\section{Various coding conventions}

\subsection{File naming}

\begin{itemize}

\item In each module, the file {\tt module.c} should only contain
initialisation and cleanup routines. It must contains {\em all}
export symbol declarations~;

\item In each module, the file {\tt module.h} should only contain
public function prototypes, type and macro definitions. By {\em
public}, we mean {\em available to other modules}. For example, all
exported functions must have their prototype defined in {\tt
module.h} as well as the types they use~;

\item In each module {\tt \_module.h} should contain private function
prototypes, type and macro definitions. This file should be included
by all source files of the module, but not by any other module. It
must include the public {\tt module.h} so that all the source files
of the module only have to include the private header~;

\item The core of the module should be implemented in files whose

\end{itemize}

\subsection{Function naming}

\begin{itemize}

\item All functions are named only with small letters and
underscores. No capital letters are used~;

should start with a prefix common to the module, for example {\tt
physmem\_get\_page} or {\tt physmem\_put\_page}~;

\item All internal functions used only in the current file should be
declared as {\tt static}~;

\item Except some specific functions, all functions should return a
{\tt result\_t}. They should use {\tt return ESUCCESS} to inform the
caller that it was successfull or {\tt return -EMYERROR} to inform
the caller that something failed. All errors are defined in {\tt
modules/kos/errno.h}~;

\end{itemize}

\end{document}