Linux Device Drivers

Linux Device Drivers


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

Linux Scheduler
Memory Management
Interrupts
Signals
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




INTER PROCESS COMMUNICATION

INTER PROCESS COMMUNICATION

 

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

 

Common methods of IPC:

ü     Pipes

ü     Shared memory

ü     Message queues etc.

 

 

PIPE

 

ü     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

 

Pipe

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

Semaphores

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.

 

 

ipcscommand

 

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

 

 

SEMAPHORES

 

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);

 

msgget

 

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.

 

msgctl

 

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.

 

Msgsnd

 

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.

 

msgrcv

 

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);

 

shmget

 

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.

 

shmat

 

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.

 

shmdt

 

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.

 

 

shmctl

 

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