System Programming Course in Alex

Useful references for who attend this course:

C/C++:

System Programming and Kernel:

Device Drivers/Kernel API:

Getting Started

Getting started:

This post is simply to simplify how to run ubuntu in a virtual machine from windows and make it ready for development. Well I will simply say what I have done and worked for me, I tried lots of stuff that didn’t work, so this is what actually worked. I installed the ubuntu iso image from the net. The first step was to create a virtual machine image and install the ubuntu.. I had choices, virtual PC 2007 or vmware player or sun virtual box… VMware player doesnot allow you to create a new image, just play existing What worked fine with me, is creating the image and installing the system with virtual pc then run it in vmware..

So the process is as follows:

  • Install Virtual PC and VMware player (both are free)
  • Create a new image in Virtual PC.
  • Boot the vm from the cd or iso image.
  • Before proceeding with the installation from the menu where you choose to install or boot from the first hard drive or whatever, you have to note that Virtual PC does not support 32 bit Graphics, so you have to press F4 and choose safe graphics mode.. that lowers it to 24 bits.
  • Continue the installation normally
  • When done with the installation, close the virtual machine and Virtual PC.
  • Run the vm from VMware… it should boot normally.

Now, everything is ready for development. Note that the ubuntu does not include the development packages by default so you have to add them.

  • From any terminal, type the following:

now, you are ready..

  • I personally, installed netbeans as an editor. It is nice and it works fine.

That’s it, you are ready to go. Of course, there could be a dozen other combination that works fine… but I hade many failed installations and problems with virtual machines so I thought I document one that worked..

I. C concepts and syntax

Part 1: C concepts and syntax:

  1. Concepts of structural programming, Makefiles, editors, environments.
  2. Typing, Declaration, Operators, Precedence and some data storage concepts.
  3. Conditionals and Loops
  4. Functions, structures, unions, and abstraction-encapsulation
  5. Pointers and arrays, memory allocation - stack vs. heap.
  6. Function Pointers, Casting, void * - Mechanism vs Policy.
  7. Debugging (this is not necessarily here, may be earlier if it's a better fit)
  8. Very brief introduction to the basic data structures: lists, trees, hash tables.

Session 1

The session resources are as follows

Presentation

Topics

  • C as a Programming Language
  • Building
  • Compiling
  • Directives and Include
  • General Guidelines
  • Empty Program
  • Data Types
  • Variables
  • Data Represenation
  • Operators
  • Precedence
  • Casting
  • Code Example

Discussion

C as a Programming Language:

  • Programming as logic
  • Language as grammar and syntax
  • Procedural
  • Modular
  • Abstraction/Hiding
  • Object-Oriented
  • C++: Parametrization or Generic Programming

Building:

  • Generating an executable from code
  • Concept of Makefile

Compiling:

  • Preprocessing – cpp
  • Compiling – gcc
  • Some important flags (-o, -c, -Wall, -L, -I, -l, -g, -O, -D, -Wl,)
  • Cross compiling

Directives and Include:

  • #include
  • #define
  • #ifdef
  • Include guards
  • What's in the include?
  • Include path “”, <>

General Guidelines

  • Maintainability/Readability
  • Flexibility/Scalability – Growth and Reduction
  • Usability
  • Re-usability of Code

Empty Program

  • Every statement ends with ;
  • Space insensitive
  • {} scopes
  • A brief intro to functions
  • main

Data Types

  • Primitive/Built-in data type controls:
  • Typical types
    • double, float
    • int, short, long, long long
    • unsigned, unsigned short, unsigned long, unsigned long long
    • char, unsigned char – ASCII
  • typedef (architecture example)

Variables

  • Data Type (Domain)
  • Scope – Variables on stack
  • Declaration
  • Global variables
  • Qualifiers
    • static
    • extern

Data Represenation

  • Writing constants
  • Chars
  • printf
  • scanf

Operators

(type)  Cast Operator
[ ]  Array Subscript
a.b  a Member of b
a->b a Member by pointer b
}
  • Unary (pre/post++, !, ~, &, *)
++a Prefix Increment
a++ Postfix Increment
!   Not
&   Address-of 
*   Indirection of (used mainly with Pointers)
~   

  • Arithmetic (*,/,%,+,-)
  • Bitwise (>>,<<,&,^,|)

==
    is equal to
!=
    is not equal to
>
    is greater than
<
    is less than
>=
    is greater than or equal to
<=
    is less than or equal to 
  • Logical (&&, ||)
&&  Logical AND
    is logical AND same meaning as the AND operator
||  Logical OR
    is logical OR same meaning as the OR operator
  • Conditional (? :)

Precedence

  • Who gets processed First?
  • Primary
  • Unary (Right associative)

Casting

  • Explicit cast
  • Implicit cast

Code Example

//Declaration
int x; char c = 'k';
int x, y;


//Explicit Casting
char x = 'a'; int y = (int) x;
int x = 5; char y = (char) x;


// Implicit cast
double a, b, c; int x; c = a*b + x;
x = a*b + c;


Session 2

The session resources are as follows:

Presentations:

C examples:

Pointers, the short version!

Actually, pointers are not exactly references. A pointer is a normal variable but it carries the memory address of another variable. That other variable can be a premitive type (char, int, bool, long, ..) or an aggregate type (Object, structure, array, ...) or a function (pointers to functions).

A point could point to anything (reference anything), that could be a pointer to an object of a class , a pointer to a structure, a point to int, to char … to anything actually. A major difference between a pointer and references is that references are managed, wether in java or .net or any other dynamic language.

A managed environment means that your JVM or .net CLR, takes care of a lot of things for you…

One of the most important of these things are pointers. To be specific, java has no pointers at all, just references. c# does support pointers.

Anyway, in c and c++ you can use a pointer to point to anything simply as follows:

int* p ;
char* p;

this is the declaration, it doesn’t point to anything now… in other languages, if you tried to use this pointer it will throw an exception , in c it wont it will simply get you the value that originally existed in the place you are pointing to… and if you attempted to write to it, you will overwrite someone else’s data or in best cases you will write in a random place where no one knows if it is used or not.

It's IMPORTANT and considered a best practice to initialize your pointers (Use NULL if you don't yet know what they will point to). Pointers are randomly initialized. If you try to access it without initializing, you can get a SEGV when you read from it and/or write to it. Depending on the random "value" it points to.

pointers are used for multiple reasons. I can't remember all of them:

  • C has no "pass by reference". You actually pass the memory address by value here (To change the value of a pointer, you need to pass a pointer to a pointer).
  • Pass by value can be bad if you have a large data structure!
  • Some data structures can only be passed as pointers.
  • In C, you can't practically do strings without pointers.
  • No dynamic memory allocation without pointers.
  • The array declaaration is a pointer to the 1st element of the array!
  • Pointers to functions are important also!

You can get the address of any variable in c using the & operator:

int  x = 0;
int* p = &x;

that way, p is pointer that points to x. to get the value in x we use the * operator:

*p  = 6; 

You could a pointer value to another with no problems:

nt* p2 = p; 

an important usage of the pointer is passing a variable by reference if we have a function as follows:

void  SomeFunctionName (int s)
{
	S = 5;
} 

And used as follows:

int x = 2;
SomeFunctionName(x);

Actually, this didn’t do anything… x will still be 2, because it is called by value, that means it sent a copy of its value to s..

It is important to note that c does not have have out-of-the-box pass by reference.

Written like this:

void  SomeFunctionName (int* s)
{
	*S = 5;
}

And used as follow:

int x = 2;
SomeFunctionName (&x);

In c an array is a pointer to the first element of the array. The point here is the dynamic allocation... Note: add the lib where the function malloc exist in malloc.h and in the code:

int* ar = (int*)malloc (10 * sizeof(int));

note: that in c you can say the following:

ar++;

What if I want to pass an array to a function I would do the following:

void foo (int* par)
{
      par[3] = 3;
}

And pass it using the following:

foo(ar);

If I tried to do that the way in the previous example, like the following:

void foo(int* par)
{
      par = (int*)malloc (10 * sizeof(int));
}

And pass it using the following:

foo(ar);

Nothing will happen, we have changed what the pointer “par” points to not what the original array points to…

For this to work, we need to make a pointer to pointer… That is written like this:

int** pp = &ar;

here we are assigning the address of the ar pointer to pp… that way we can do the following:

*pp  =  (int*)malloc (10 * sizeof(int));

That will change the value of ar… Thus we could do the following to the function:

void foo(int** par)
{
*par = (int*)malloc (10 * sizeof(int));
}

And pass it using the following:

foo(&ar);

That’s all… my goal was to overview the pointers briefly… you will have some long book in the c to get it all but this is the short version… Thank you.

Simple Examples

Simple Examples

Example 1: Prints Hello World

#include <stdio.h>

int main()
{
  printf( "Hello World\n" );
  return 0;
}

Example 2: Declare Variables

#include <stdio.h>
int main() 
{
    int x;
    printf( "Declare x first\n" );
    return 0;
}

Example 3: If Else

#include <stdio.h>	

int main()            /* Most important part of the program! */
{
    int age;                          /* Need a variable... */
    printf( "Please enter your age" );  /* Asks for age */
    scanf( "%d", &age );                 /* The input is put in age */
    if ( age < 100 ) {                  /* If the age is less than 100 */
    printf ("You are pretty young!\n" ); /* Just to show you it works... */
  }
else if ( age == 100 ) {            /* I use else just to show an example */ 
     printf( "You are old\n" );       
  }
  else {
    printf( "You are really old\n" );     /* Executed if no other 
statement is */
  }
  return 0;
}

Example 4: For Loop

#include <stdio.h>

int main()
{
    int x;
    /* The loop goes while x < 10, and x increases by one every loop*/
    for ( x = 0; x < 10; x++ ) {
        /* Keep in mind that the loop condition checks 
           the conditional statement before it loops again.
           consequently, when x equals 10 the loop breaks.
           x is updated before the condition is checked. */   
        printf( "%d\n", x );
    }
    getchar();
}

Example 5: While Loop

#include <stdio.h>

int main()
{
    int x;
    /* The loop goes while x < 10, and x increases by one every loop*/
    for ( x = 0; x < 10; x++ ) {
        /* Keep in mind that the loop condition checks 
           the conditional statement before it loops again.
           consequently, when x equals 10 the loop breaks.
           x is updated before the condition is checked. */   
        printf( "%d\n", x );
    }
    getchar();
}

Example 6: Do While Loop

#include <stdio.h>

int main()
{
  int x;

  x = 0;
  do {
    /* "Hello, world!" is printed at least one time
      even though the condition is false*/
    printf( "%d\n", x );
  } while ( x != 0 );
  getchar();
}

Session 3

Presentations:

  1. Part 1: by Eng.Riham AlDakkak: not uploaded yet.

Session 4

Presentation:

libipc

This is a page for the libipc educational project that we discussed in the course. The main target was to get people acquainted with writing actual C code.

I am not going to go over the design in detail here. Just the main line.

We will write a shared library that can be used to perform IPC (inter-process communication). The library should provide the user with simple and unified interface to perform several "types" of IPC. Such as file based, shared memory, network based..etc. The library should be plugin based, i.e. you can add/remove IPC methods with as little as code modification as possible and with the interface remaining the same.

This is basically the main requirement. I gave it a try and put the code on a public SVN repository to share the code with the other guys in the course. Comments and contributions are welcomed!

session 6

This is a very draft draft for what happened in session 6 written while the session is running.

Review of what we are doing:

now we have made libIPC which is a shared library. meant to handle InterProcess Communications.

the library should be pluggable, currently we should implement FileIO which can be a shared library too. later we should implement SharedMem , Sockets, .. etc

we will use function pointers to handle multiple instances of the same function.

there was a rough review about the requirements of the design that we agreed on the last session. more details is to be added here

MakeFiles

normally when we install a new package, the normal way is to ./configure, make, make install when you ./configure, you are actually building the MakeFile... this is done by certain instructions in a file targeted for automake to create the make file. the value of this is portability, pass a parameter to the builder, ... etc.

talk about what does libtool , autoconf, automake do here

when we start making automake you start by making configure.ac

SUBDIRS: <== this is to show where the code is, if it's not in the root of the project

bin_PROGRAMS=hello

hello_SOURCES=main.c <= this is to override the default which is hello.c

  • showcase of configure.ac implementation in sysfsutils-2.1.0

when you want to know what configure flags just type ./configure --help and it will give standard configure flags + optional flags (package specific).

to know all vriables/directives that you can put in configure.ac file just type info automake at the bash prompt.

overview of datastructures:

  • example of sorting a one dimentional array.
  • tree structure (AVL trees, Red-Black Trees): we should choose one to talk about the coming session.
  • hash tables.

Next session is to be C++ and we'll continue with automake

II. C++ and Object-oriented programming

Part II: C++ and Object-oriented programming:

  1. Classes
  2. Inheritance
  3. Operator overloading
  4. Polymorphism
  5. Templates and introductory meta-programming
  6. The STL library
  7. Some design patterns and programming techniques

session 1

this is a draft writtin inside the class while it's running

Why C++

Object Oriented Concepts

in object oriented we don't think about procedures, we think about objects that interact together, we don't try to explore all paths that the logic may run through

Instance vs type

isa

  • abstraction/hiding made easier
  • Object behaviour modification: more goes here
  • Generic programming
    • type independance : more goes here
  • Inter-object interaction
    • design: more goes here

note about over architecting of a program.

References

  • an object naming: compiler handles it, it doesn't have to be a pointer. It's abstracting you from dealing with memory.
  • Declaration: in compiler messages it's called Lvalue
x=5;
int& ref=x;

you can't say it's ok to say but it's not useful to use it.

functions

  • Overloading:

you can overload the function as the function signature is different, you can redefine the function

  • function signature

includes the passed variables, and their types

differs from so when you call a function it depends on your passed variable to call which function. but you can always cast.

  • Default arguments:

only the last n arguments, not in the middle.. not that you already took to function signature, one takes int & chat, and one taking only int for example)

Scopes

  • namespace can be nested
{
  namespace y
    {
       int fun()
       .
       .
    }
}

Class

  • it's the central concept in C++
  • Class as object type

III. Application system programming concepts

Part III: Application system programming concepts (the focus will be on Linux but the concepts and many of the prototypes are applicable throughout POSIX):

  1. User-space, process and address space concepts, shared objects and code loading.
  2. Threading (pthreads)
  3. IPC using POSIX and SYSV
  4. File operations and System calls
  5. Sockets

IV. Driver/Kernel Module programming concepts

Part IV: Driver/Kernel Module programming concepts (Linux only, but the concepts do carry through other OSes):

  1. Mechanism vs. Policy and the C implementation of interfaces/strategy pattern, Makefiles
  2. File ops - synchronous vs asynchronus, calls, context
  3. Debugging
  4. Mutual exclusion
  5. Interrupts and tasklets
  6. Memory concepts, allocation, mapping
  7. Introduction to subsystems and the driver model, sysfs/procfs