FreeNOS Developers Handbook

Introduction

Reading books about the theory of operating systems can help you understand most of their concepts, but to learn more you need to program them in practice using a real computer. This guide can help you to get started with developing application programs, libraries, device drivers, filesystems and more for FreeNOS, on your own computer.

Getting Started

This section explains how to get started with developing FreeNOS code on your computer. We assume you can operate a UNIX-like computer using a terminal console, and that you have at least some programming experience, preferably in C/C++.

Requirements

Before you can start writing code for FreeNOS, you first need to have at least the following:

  • A Computer running any of the supported operating systems.
  • An Intel x86 C/C++ compiler such as GCC .
  • An Editor.
  • SCons for automatic compilation.
  • Subversion to obtain the FreeNOS source code.

The following paragraphs explain how to install the required development programs on the operating system distrubution of your choice:

Ubuntu

$ sudo aptitude install build-essential scons python-subversion subversion qemu 

Gentoo

# USE="python ncurses" emerge subversion qemu scons

OpenBSD

# pkg_add scons py-subversion subversion qemu 

Obtaining FreeNOS

Once you installed the required development programs, the next step is to download the FreeNOS source code from our Subversion repository. Subversion is a version management program, which makes it easy to update and share files in a project with multiple programmers. To simply download the latest code to your system, use the following command:

$ svn co http://freenos.googlecode.com/svn/trunk FreeNOS

This will create a new directory 'FreeNOS' containing all source files. Also see our subversion page for more details.

Building FreeNOS

FreeNOS uses a Python program called SCons to automate the process of building the applications, libraries, servers and kernel. It is available for any platform which has a Python interpreter. As a developer, you can invoke SCons to let it compile FreeNOS and generate a bootable ISO 9660 filesystem:

$ cd /path/to/FreeNOS
$ scons iso

If your computer has multiple CPU cores, you can compile FreeNOS quicker by letting all CPU cores compile instead of only one. SCons provides a flag -j to specify the number of compile jobs (or threads) to create. It can be beneficial for performance to start more compile threads than your total number of CPU cores, because then a number of threads can wait for I/O from disk, while others are using the CPU units. For example, if you have two CPU cores and want to start 5 jobs to compile FreeNOS, simply use:

$ cd /path/to/FreeNOS
$ scons -j 5 iso

Running FreeNOS

To run FreeNOS, you can choose to use a virtual machine or real hardware. The advantage of using a virtual machine is that you do not need to wait for hardware to initialize, and meanwhile save power and space. Additionally, many virtual machines provide an interface for debuggers to actively inspect the code while it runs. Also see Debugging FreeNOS.

An excellent virtual machine solution is Qemu . It can virtualize many CPU architectures, hardware devices and busses. To run a new instance of Qemu in a separate window, use the following command:


To run FreeNOS in curses mode, try this command:

Debugging FreeNOS

Coding Style

This section describes guidelines to the suggested coding style in FreeNOS. It is designed to help structure your code in such a way, that it will be more readable for yourself and others. Note that these are merely guidelines: it is not forbidden to ignore them, if there is a good reason to do so.

Layout

When programming a component in FreeNOS, it can be beneficial for code readability to use the following “rules of thumb”:

  • Keep the width of the code to 76 characters maximum. This allows systems with a 80×25 VGA screen to view the code in an editor. Additionally, it saves 4 characters for quoting code in e-mail clients, which usually insert an '>' character before quoted text.
  • Avoid writing long (complicated) source code. Short source code files are easier to understand: split up files if they grow too big (about 500 lines).
  • Use 4 white spaces to indent your code. Using a tab character to indent code may be displayed differently in various editors, sometimes even a bit too wide.

Variables

Declaration
  • Declare Variables at the beginning of the function body. This convention makes it easier to see in a flash which variables are used in a function.
Names
  • Variable names should be as descriptive as possible, yet readable. Prevent cryptic names like pd; just write parentDevice. For temporary variables it is OK to use short names, as long as it remains clear for the reader what it is used for.
  • Avoid using special characters in variable names. This includes the underscore, dollar and number characters.
  • Start variable names with a lowercase first letter. Internal words in the variable names start with a capital, for example: char * clientUserName
Doxygen Tags
  • Variables declared in header files must have descriptive doxygen tags. At least the @brief tag should be used for a variable, for example:
/** @brief Number of characters horizontally. */
Size width;

Functions

  • Avoid writing long (complicated) functions. Short functions are easier to understand: split up functions if they grow over about two pages in size (about 100 lines).
  • Place brackets on a new separate line. This makes it easier to spot where brackets are opened and closed, as the closing bracket is always placed directly underneath the opening bracket.
  • Keep the number of arguments to a minimum. Functions are more easy to understand and read when they take only a few arguments (about 6 maximum).
  • Always place Doxygen tags for functions in header files. Document functions so that you (and others) can read what it is used for. Use (at least) the @brief tag, and @param, @return and @see where appropriate.

The following example illustrates the declaration and implementation of a simple C function called writeLog.

logging.h:

#include <Macros.h>
 
/**
 * @brief Log a message.
 *
 * This function performs logging of
 * messages to the system console using printf().
 *
 * @param message String to log.
 * @return Zero on success and non-zero on failure.
 * @see printf
 */
extern C int writeLog(const char *message);

logging.c:

#include <stdio.h>
#include "logging.h"
 
int writeLog(const char *message)
{
    printf("Log message: %s\r\n", message);
    return 0;
}

Conditionals

  • Always use brackets to define the scope of a conditional. Do not leave brackets out for conditionals, even with one-line statements. This avoids confusion of the conditional's scope, and keeps their layout consistent throughout the FreeNOS code.
  • Place brackets on a new separate line. Like functions, this makes it easier to spot where brackets are opened and closed, as the closing bracket is always placed directly underneath the opening bracket.
  • Put a white space between the conditional and parentheses. Having one white space between for example an if and the parenthesis with a conditional expression can help to improve code readability.
  • Write a 'default' label in switch statements. This can avoid compiler warnings, and may catch possible programming or input errors.
  • Keep the number of nested conditionals low. Do not write code with more than 3 nested if statements, as it would be harder to read and debug.
  • Place the default label in a switch() last. This makes it easier to spot the default label.

Is there a better way of showing how conditionals should be written than through an example? Enjoy.

/*
 * Examples of conditional statements.
 */
 
/* Correct if statement. */
if (condition)
{
    foo();
}
else if (otherCondition)
{
    bar();
}
 
/* Correct while statement. */
while (true)
{
    FreeNOS::showCoolness();
}
 
/* Correct do-while statement. */
do
{
    FreeNOS::showCoolness();
}
while (true);
 
/* Correct for statement. */
for (int i = 0; i < 1337; i++)
{
    checkLeetness();
}
 
/* Correct switch statement. */
switch (condition)
{
    case FreeNOS:
        statements;
 
    /* Falls through until OSX */
    case Linux:
    case OSX:
       doStuff();
       break;
 
    /*
     * If nothing else fits, the default label is executed.
     */
    default:
        statements;
        break;
}

Loops

  • Place brackets on a new separate line. Like for functions and conditionals, this makes it easier to spot where brackets are opened and closed, as the closing bracket is always placed directly underneath the opening bracket.
  • Always use brackets to define the scope of a loop. Like conditionals, do not leave brackets out for loops, even with one-line statements. This avoids confusion of the scope of loops, and keeps their layout consistent throughout the FreeNOS code.
  • Avoid nested loops of more than three levels. Unless you really need them, many nested loops is a Bad Thing®. It makes your code slow, unattractive, and harder to read, let alone understand it.

This example shows the suggested coding style of loops:

/*
 * A commonly used for loop.
 */
for (int i = 0; i < 10; i++)
{
    /* Do stuff. */
}
 
/*
 * A commonly used while loop.
 */
while (condition)
{
    /* Do stuff. */
}

This examples illustrates why you shouldn't nest more than three loops:

int[10][10][10][10][10] myMatrix;
 
/*
 * Many nested loops can be a really Bad Thing(R).
 */
for (int i = 0; i < 10; i++)
{
    for (int j = 0; j < 10; j++)
    {
        for (int k = 0; k < 10; k++)
        {
            for (int l = 0; l < 10; l++)
            {
                for (int m = 0; m < 10; m++)
                {
                    myMatrix[i][j][k][l][m] = 1;
                }
            }
        }
    }
}

Headers

Classes

Comments

Templates

Files

Applications

Example 1: Hello, World!

Example 2: Echo

Example 3: Stat

Libraries

Devices

Example 1: Hello Driver

Example 2: Time Driver

Example 3: Serial Driver

FileSystems

 
documentation/freenos-developers-handbook.txt · Last modified: 2009/08/21 17:19 by nlinnenbank     Back to top