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




A mechanism to communicate & share data among multiple running processes.


Common methods of IPC:


     Shared memory

     Message queues etc.





     Data flow from one process to another

     Generally it is done by attaching the output of one process to the input of another

     pipe -Half Duplex. Data flows only in one direction

     only between processes that have a common ancestor



A pipe is created by calling the "pipe" function.

#include <unistd.h>

int pipe ( int fd[2] );

Returns: 0 if ok, -1 on error


Two file descriptors are returned: fd[0] is open for reading and

fd[1] is open for writing.



     A pipe in a single process is next to useless

     IPC channel from parent to child or vice versa


For a pipe from the parent to the child:

parent closes the read end of the pipe fd[0]

child closes the write end of the pipe fd[1]


For a pipe from the child to the parent:

parent closes the write end of the pipe fd[1]

child closes the read end of the pipe fd[0]


Technically it is possible to duplicate pipe descriptor for writing.


LIMITATION: If multiple processes are writing to a pipe descriptor and we write more than PIPE_BUF bytes ( kernels Pipe buffer size), the data might be interleaved with the data from the other writers.


popen & pclose for pipes


#include <stdio.h>

FILE *popen( const char *Cmdstring, const char *type);

Returns fp if ok, NULL on error.


int pclose ( FILE *fp);

Returns termination status of Cmdstring, or -1 on error.


     If type is r , the fp is connected to the stdout of Cmdstring

     If type is w, the fp is connected to the stdin of Cmdstring.


Named Pipes: FIFOS


     Special type of file that exists as a name in the file system

     Allows exchange of data between unrelated processes


FIFOS using command line program

$ mknod filename p (or)

$ mkfifo filename

$ cat < filename &

$ echo hello > filename


Creating FIFOs from inside a program


# include < sys/types.h >

# include < sys/stat.h >

int mkfifo( const char *filename, mode_t mode );

int mknod ( const char *filename, mode_t mode | S_IFIFO, ( DEV_T)0);


A FIFO exists as a named file, not as an open file descriptor, and must be opened before it can be read from or written to.


open ( const char *path, O_RDONLY);

Open blocks until a process opens the same FIFO for writing


open ( const char *path, O_RDONLY | O_NONBLOCK);

Open succeeds and returns immediately, even if the FIFO had not been opened for writing by any process.


open ( const char *path, O_WRONLY);

Open blocks until a process opens the same FIFO for reading.


open ( const char *path, O_WRONLY | O_NONBLOCK);

returns 1 and the FIFO not opened, if no process has the FIFO open for reading.


     A read on an empty blocking FIFO will wait until some data can be read

     A read on a non-blocking FIFO with no data will return 0 bytes.

     A write on a full blocking FIFO will wait until data can be written.


System V IPC


A mechanism to communicate and share data among multiple running processes. The three types of IPC:

Message queues


Shared memory

Are collectively referred to as System V IPC


A summary of these system calls is shown in the following table:


Message queue Semaphore Shared memory


Include file <sys/msg.h> <sys/sem.h> <sys/shm.h>


System call to msgget semget shmget

create or open


System call for msgctl semctl shmctl

control operations


Systems calls for msgsnd semop shmat

IPC operations msgrcv shmdt


key_t Keys


The function ftok() is provided by System V standard C library to convert a path name and project identifier into a System V IPC key. These system V keys are used to identify message queues, shared memory, and semaphores.

#include <types.h>

#include <sys/ipc.h>


key_t ftok(char *pathname, char proj);


The key_t data type is a 32bit integer.

The path name could be path of common data file name, server name or other path name in the system.

The proj argument is an 8-bit character.





The ipcscommand provides information on IPC facilities, including shared segments. Use the -m flag to obtain information about shared memory.


For example, this code illustrates that one shared memory segment, numbered 1627649, is in use:

% ipcs-m

------Shared Memory Segments --------

key shmid owner perms bytes nattch status

0x00000000 1627649 user 640 256 00 0


If this memory segment was erroneously left behind by a program, you can use the ipcrm command to remove it.

% ipcrm shm1627649





A semaphore is a special variable that takes only whole numbers and upon which only two operations are allowed:

Wait and Signal

P ( Semaphore variable ) for wait.*

V ( Semaphore variable ) for signal. *

*Atomic operations


P(SV) if SV is greater than zero, decrement SV. If SV is zero suspend execution of this process.

V(SV) if some other process has been suspended waiting for SV, make it resume execution. If no process is suspended waiting for SV, increment SV.


All the UNIX Semaphore functions operate on arrays of general semaphores.


Header files needed are:


#include < sys/types.h>

#include < sys/ipc.h>

#include < sys /sem.h>


Function definitions are:


int semctl (int semid, int num_sems, int sem_flags);

int semget ( key_t key, int num_sems, int sem_flags);

int semop ( int semid, struct sembuf *sem_ops, size_t num_sem_ops);


semget: The semgetfunction creates a new Semaphore or obtains the semaphore key of an existing semaphore.


int semget ( key_t key, int num_sems, int sem_flags);


key: is an integral value used to allow unrelated processes to access the same semaphore.

num_sems: number of semaphores required.

sem_flags: lower nine bits are the permissions for the semaphore (similar to file permissions)

Other flags are IPC_CREAT, IPC_EXCL


Returns Semaphore id ( a +ve integer) or 1 on error.


semop: The function semopis used for changing the value of the semaphore.


int semop(int sem_id, struct sembuf *semops,size_t num_sem_ops);


sem_id : Semaphore identifier, as returned from semget

sem_ops : a pointer to an array of structures of type sembuf


struct sembuf {

short sem_num ; //semaphore number( starts with 0 )

short sem_op ; // Value by which the semaphore should

// be changed

//-1 for wait ( P ) req. alter perm

//+1 for signal ( V ) req. alter perm

short sem_flg; //SEM_UNDO, IPC_NOWAIT



num_sem_ops: number of operations.


Operations will be performed if and only if all of them will succeed.


semctl: The semctlfunction allows direct control of semaphore information.


intsemctl( intsem_id, intsem_num, intcommand, union semunarg);


union semun


int val;

struct semid_ds *bf ;

unsigned short *array;



Commands: IPC_RMID: Remove the semaphore set.

GETALL: get "semval" for all semaphores of the set

GETVAL: get "semval" of nth semaphore

SETVAL set "semval" for all the semaphores of the set to "val"


Message Queues



Message queues are linked lists of messages stored within a kernel and identified by a message queue identifier.


Header files needed are:

# include < sys/types.h >

# include < sys/ipc.h >

# include < sys/msg.h >


Message queue provide a way of sending a block of data from one process to another along with a type.

System V message queue structures in kernel



The message queue function definitions are :


int msgget( key_tkey, intmsgflg) ;

int msgsnd( intmsgid, const void *msg_ptr, size_tmsg_sz, intmsgflg);

int msgrcv( intmsgid, void *msg_ptr, size_tmsg_sz, long intmsgtype, intmsgflg) ;

int msgctl( intmsgid, intcmd, structmsqid_ds*buff);




A new message queue is created, or an existing message queue is accessed.


#include <sys/msg.h>

int msgget (key_t key, int oflag);

Returns non-negative identifier if OK, -1 on erroroflagis a combination of the read-write permissions. Thus can be bitwise ORed with IPC_CREAT.




It provides a variety of control operations on a message queue.


#include <sys/msg.h>

int msgctl(intmsqid, intcmd, structmsqid_ds*buf);

Returns 0 if OK, -1 on error


IPC_RMID Remove the message queue specified by msqid.

IPC_SET Set the members of the msqid_ds structure for the

message queue

IPC_STAT Return to the caller the current msqid_ds structure.




Once a message queue is opened, we put a message onto the queue

using msgsnd.


#include <sys/msg.h>

int msgsnd(intmsqid, const void *ptr, size_tlength, intflag);

Returns 0 if OK, -1 on error


msqid is an identifier returned by msgget.

ptr is a pointer to a structure with the following template,


struct msgbuf{

long mtype;/* message type, must be > 0 */


char mtext[1];/* message data */



flag can be either 0 or IPC_NOWAIT.




A message is read from a message queue using msgrcv function.


#include <sys/msg.h>

int msgrcv(intmsqid, void *ptr, size_t length, long type, int flag);


Returns number of bytes of data read into buffer if OK, -1 on error

msqid is an identifier returned by msgget.

ptr specifies where the received message is to be stored.

length specifies the size of the data portion of the buffer pointed to by ptr.

type specifies which message on the queue is desired.

if type is 0, the first message on the queue is returned.

if type is greater than 0, the first message whose type equals

is returned.


Shared Memory


     Allows two unrelated processes to access the same logical memory

     Very efficient way of transferring data between running processes

     If one process write to the shared memory the changes immediately become visible to any other process that has access to the same shared memory

     Synchronizing the access is the responsibility of the programmer


Shared memory structure


For every shared memory segment, the kernel maintains the following information, defined in <sys/shm.h>


struct shmid_ds


struct ipc_perm shm_perm; /* operation permission struct*/

size_tshm_segsz; /* segment size */

pid_tshm_lpid; /* pidof last operation */

pid_tshm_cpid; /* creator pid*/

shmatt_tshm_nattach; /* current # attached */



time_t shm_ctime; /* last change time of struct*/



Shared memory Functions


The functions for creating and handling shared memory:

#include <sys/shm.h>


int shmget( key_tkey , size_tsize, intshmflg);

void *shmat( intshm_id, const void *shm_addr, intshmflg) ;

int shmdt( const void *shm_addr);

int shmctl( intshm_id, intcmd, structshmid_ds*buf);




A shared memory segment is created, or an existing one is accessed.


#include <sys/shm.h>

int shmget(key_tkey, size_tsize, intoflag);

Returns shared memory identifier if OK, -1 on error


key can be either a value returned by ftok or the constant IPC_PRIVATE.

size specifies the size of the segment in bytes.

oflag is a combination of the read-write permissions Thus can be bitwise-ORed with IPC_CREAT.




After a shared memory segment is created or opened, we attach it to our address space.


#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int flag);


Returns starting address of mapped region if OK, -1 on error


If shmaddr is a null pointer, the system selects the address for the caller.

flag is SHM_RND.




When a process is finished with a shared memory segment, it detaches. The segment.

#include <sys/shm.h>

int shmdt(const void *shmaddr);

Returns 0 if OK, -1 on error


When a process terminates, all shared memory segments currently attached by the process are detached.





It provides a variety of operation on a shared memory segment.


#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds*buf);


Returns 0 if OK, -1 on error


Three commands are provided:

IPC_RMID Remove the shared memory segment identified by shmid

IPC_SET Set the permission in the structure.

IPC_STAT Return the caller the current shmid_ds structure.


Shared memory limits


Max #bytes for a shared memory segment 4MB

Min #bytes for a shared memory segment 1

Max #shared memory identifiers, systemwide 128

Max #shared memory segments attached per process 32