Linux Device Drivers

Linux Device Drivers

Character drivers
IO & Memory
Linux Kernel
Process Management
Process Address space

Linux Scheduler
Memory Management
System Calls
Kernel Synchronization
Linux Inter Process Communications

Serial Ports
Parallel Ports
Introduction to Hardware
Linux Timers
DMA in Linux
Linux Threads
Linux Thread Synchronization

Linux Multi Threading
Debugging in Linux
GDB GNU Debugger
KDB Kernel Debugger
KGDB Kernel GNU Debugger
Example Ethernet Driver




In the traditional Unix model, when a process needs something performed by another entity, it forks a child process. There are problems with a fork:


     Fork is expensive. Memory is copied from the parent to the child, all the descriptors are duplicated in the child. Current implementation use a technique called copy-on-write, which avoids a copy of the parents data space to the child until the child needs its own copy.

     Intrer-process-communication is required to pass information between the parent and child after the fork.


Threads help with both problems. Threads are sometimes called lightweight processes. Thats is a thread creation can be 10-100 times faster than process creation time.


All threads with in a process share the same global memory. This makes the sharing of information easy between the threads, but along with this simplicity comes the problem of synchronization.


All threads with in a process share:

     Process instructions

     Most data

     Open files (e.g. descriptors)

     Signal handlers

     Current working directory

     User and group Ids


But each thread has its own:

     Thread ID

     Set of registers, including program counter and stack pointer

     Stack (for local variables and return addresses)


     Signal mask





Linux implements the POSIX standard thread API (known as pthreads). All thread functions and data types are declared in the header file <pthread.h>.


The pthread functions are not included in the standard C library. Instead, they are in libpthread, so you should add -lpthreadto the command line when you link your program.




When a program is started by exec, a single thread is created, called the initial thread or main thread. Additional threads are created by pthread_create.


#include <pthread.h>

intpthread_create(pthread_t*tid, const pthread_attr_t*attr,

void *(*func) (void *), void *arg);

Returns 0 if OK, positive Exxxvalue on Error


Each thread within a process is identified by a thread ID, whose data type is pthread_t. On successful creation of a new thread, its ID is returned through the pointer tid.


Each thread has numerous attributes: its priority, its initial stack size, whether it should be daemon thread or not, and so on. When a thread is created, we can specify these attributes by initializing a pthread_attr_t variable that overrides the default. We normally take the default, we specify the attr argument as a null pointer.


When we create a thread, we specify a function for it to execute, called its thread start function. The thread starts by calling this function and then terminates either explicitly (by calling pthread_exit) or implicitly (by letting this function return).


The address of the function is specified as the func argument, and this function is called with a single pointer argument, arg.




We can wait for a given thread to terminate by calling pthread_join.

Comparing threads to Unix processes, pthread_createis similar to fork, and pthread_joinis similar to waitpid.


#include <pthread.h>

int pthread_join(pthread_t tid, void **status);


Returns 0 if OK, positive Exxxvalue on error




Each thread has an ID that defines it with in a given process. The thread ID is returned by pthread_create. A thread fetches this value for itself using pthread_self.


#include <pthread.h>

pthread_t pthread_self(void);


Returns thread ID of calling thread




A thread is either joinable (the default) or detached. When a joinable thread terminates its thread ID and exit status are retained until another thread in the process calls pthread_join. But a detached thread is like a daemon process: when it terminates, all its resources are released, and we cannot wait for it to terminate.


#include <pthread.h>

int pthread_detach(pthread_t tid);


Returns 0 if OK, positive Exxx value on error




One way for a thread to terminate is to call pthread_exit.


#include <pthread.h>

void pthread_exit(void *status);


Does not return to caller

If the thread is not detached, its thread ID and exit status are retained for a later pthread_join by some other thread in the calling process.