104
2.3 InterProcess 2.3 InterProcess Communication Communication (IPC) (IPC)

2.3 InterProcess Communication (IPC). IPC methods ► Signals ► Mutex (MUTual EXclusion) ► Semaphores ► Shared memory ► Memory mapped files ► Pipes & named

Embed Size (px)

Citation preview

2.3 InterProcess 2.3 InterProcess Communication (IPC)Communication (IPC)

IPC methodsIPC methods

► SignalsSignals►Mutex (MUTual EXclusion)Mutex (MUTual EXclusion)► SemaphoresSemaphores► Shared memoryShared memory►Memory mapped filesMemory mapped files► Pipes & named pipesPipes & named pipes► SocketsSockets►Message queuesMessage queues►MPI (Message Passing Interface)MPI (Message Passing Interface)► BarriersBarriers

IPC methodsIPC methods

1.1. thread to threadthread to thread

2.2. process to process (both on same process to process (both on same system)system)

3.3. system to system (i.e., processes on system to system (i.e., processes on different systems)different systems)

IPC methods IPC methods between between threadsthreads

►MutexMutex

►SemaphoresSemaphores

IPC methods IPC methods between between processesprocesses

►SignalsSignals

►Shared memoryShared memory

►Memory mapped filesMemory mapped files

►Pipes & named pipesPipes & named pipes

►Message queuesMessage queues

IPC methods IPC methods between between systemssystems

►SocketsSockets

►MPI (Message Passing Interface)MPI (Message Passing Interface) BarriersBarriers

SignalsSignals

SignalsSignals

►software interruptssoftware interrupts

►asyncasync

►can be recognized or ignoredcan be recognized or ignored

SignalsSignals

#include <signal.h>#include <signal.h>

//defn. of signal handler function//defn. of signal handler functiontypedef void (*sighandler_t)(int);typedef void (*sighandler_t)(int);

//function call to establish a signal //function call to establish a signal handlerhandler

sighandler_t signal ( int signum,sighandler_t signal ( int signum,sighandler_t handler );sighandler_t handler );

What is this?

Remember . . .Remember . . .

char* ptr1, ptr2;char* ptr1, ptr2;

is not the same asis not the same as

char* ptr1;char* ptr1;

char* ptr2;char* ptr2;

It really meansIt really means

char *ptr1, ptr2;char *ptr1, ptr2;

UseUse

char *ptr1, *ptr2;char *ptr1, *ptr2;

instead.instead.

Allowed signals (see kill –l)Allowed signals (see kill –l) 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR29) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR213) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO30) SIGPWR 31) SIGSYS 32) SIGRTMIN 33) SIGRTMIN+130) SIGPWR 31) SIGSYS 32) SIGRTMIN 33) SIGRTMIN+134) SIGRTMIN+2 35) SIGRTMIN+3 36) SIGRTMIN+4 37) SIGRTMIN+534) SIGRTMIN+2 35) SIGRTMIN+3 36) SIGRTMIN+4 37) SIGRTMIN+538) SIGRTMIN+6 39) SIGRTMIN+7 40) SIGRTMIN+8 41) SIGRTMIN+938) SIGRTMIN+6 39) SIGRTMIN+7 40) SIGRTMIN+8 41) SIGRTMIN+942) SIGRTMIN+10 43) SIGRTMIN+11 44) SIGRTMIN+12 45) 42) SIGRTMIN+10 43) SIGRTMIN+11 44) SIGRTMIN+12 45)

SIGRTMIN+13SIGRTMIN+1346) SIGRTMIN+14 47) SIGRTMIN+15 48) SIGRTMAX-15 49) SIGRTMAX-1446) SIGRTMIN+14 47) SIGRTMIN+15 48) SIGRTMAX-15 49) SIGRTMAX-1450) SIGRTMAX-13 51) SIGRTMAX-12 52) SIGRTMAX-11 53) SIGRTMAX-1050) SIGRTMAX-13 51) SIGRTMAX-12 52) SIGRTMAX-11 53) SIGRTMAX-1054) SIGRTMAX-9 55) SIGRTMAX-8 56) SIGRTMAX-7 57) SIGRTMAX-654) SIGRTMAX-9 55) SIGRTMAX-8 56) SIGRTMAX-7 57) SIGRTMAX-658) SIGRTMAX-5 59) SIGRTMAX-4 60) SIGRTMAX-3 61) SIGRTMAX-258) SIGRTMAX-5 59) SIGRTMAX-4 60) SIGRTMAX-3 61) SIGRTMAX-262) SIGRTMAX-1 63) SIGRTMAX62) SIGRTMAX-1 63) SIGRTMAX

► Also see man 7 signal for a lengthier description.Also see man 7 signal for a lengthier description.

As reported by kill -l on As reported by kill -l on SunOS/Solaris (Sun’s Unix)SunOS/Solaris (Sun’s Unix)

►HUP, INT, QUIT, ILL, TRAP, ABRT, EMT, HUP, INT, QUIT, ILL, TRAP, ABRT, EMT, FPE, KILL, BUS, SEGV, SYS, PIPE, ALRM, FPE, KILL, BUS, SEGV, SYS, PIPE, ALRM, TERM, USR1, USR2, CLD, PWR, WINCH, TERM, USR1, USR2, CLD, PWR, WINCH, URG, POLL, STOP, TSTP, CONT, TTIN, URG, POLL, STOP, TSTP, CONT, TTIN, TTOU, VTALRM, PROF, XCPU, XFSZ, TTOU, VTALRM, PROF, XCPU, XFSZ, WAITING, LWP, FREEZE, THAW, WAITING, LWP, FREEZE, THAW, CANCEL, LOST, XRES, JVM1, JVM2, CANCEL, LOST, XRES, JVM1, JVM2, RTMIN, RTMIN+1, RTMIN+2, RTMIN+3, RTMIN, RTMIN+1, RTMIN+2, RTMIN+3, RTMAX-3, RTMAX-2, RTMAX-1, RTMAXRTMAX-3, RTMAX-2, RTMAX-1, RTMAX

Sending a signal to a processSending a signal to a process

►Use the kill command (see man kill).Use the kill command (see man kill). kill [ -s signal | -p ] [ -a ] [ -- ] pid ...kill [ -s signal | -p ] [ -a ] [ -- ] pid ... kill -l [ signal ]kill -l [ signal ]

►Use the kill function (see man 2 kill)Use the kill function (see man 2 kill)#include <sys/types.h>#include <sys/types.h>#include <signal.h>#include <signal.h>

int kill ( pid_t pid, int sig );int kill ( pid_t pid, int sig );

Signal example codeSignal example code

//define the signal hander function//define the signal hander functionvoid myHandler ( int signalNo ) {void myHandler ( int signalNo ) {

……}}

……//define the signal handler//define the signal handler// (typically done once in main)// (typically done once in main)signal( SIGCHLD, myHandler );signal( SIGCHLD, myHandler );

MutexMutex

Used to control access to Used to control access to shared memory and other shared memory and other

resources, in general.resources, in general.

Race conditionRace condition

► An error whereAn error where one process may wait foreverone process may wait forever or other inconsistencies may resultor other inconsistencies may result

►Occurs when two or more processes are Occurs when two or more processes are reading or writing some shared datareading or writing some shared data

► Applies to threads as wellApplies to threads as well► The final result depends on process or The final result depends on process or

thread runs, precisely when they run, and in thread runs, precisely when they run, and in what order they run.what order they run.

►Difficult to debug and reproduce errors.Difficult to debug and reproduce errors.

Critical region/sectionCritical region/section

►Part of program where shared memory Part of program where shared memory is accessedis accessed Must be identifiedMust be identified

► mutual exclusion (mutex)mutual exclusion (mutex) method to exclude other processes from method to exclude other processes from

using a shared variable until our process using a shared variable until our process is finished with itis finished with it

Process cooperation rules:Process cooperation rules:

1.1. No two processes can be in their critical No two processes can be in their critical sections at the same time.sections at the same time.

2.2. Make no timing assumptions.Make no timing assumptions.► My code is faster/shorter; my processor is faster.My code is faster/shorter; my processor is faster.► My priority is higher.My priority is higher.► The probability is small for us both processes to do The probability is small for us both processes to do

this at the same time.this at the same time.

3.3. (progress) A process should not be (progress) A process should not be blocked from entering a critical region if all blocked from entering a critical region if all other processes are outside the critical other processes are outside the critical region.region.

4.4. (bounded wait) No process should have to (bounded wait) No process should have to wait forever to get into its critical region.wait forever to get into its critical region.

Mutual exclusion w/ busy Mutual exclusion w/ busy waitingwaiting

Methods to implement mutex:Methods to implement mutex:

1.1. Disable interruptsDisable interrupts

2.2. Lock variablesLock variables

3.3. Strict alternationStrict alternation

4.4. Peterson’s solutionPeterson’s solution

5.5. TSL instructionTSL instruction

Mutex method 1: disable Mutex method 1: disable interruptsinterrupts

►OK for (and used by) OSOK for (and used by) OS Consideration for MP systemsConsideration for MP systems

►NOT OK for appsNOT OK for apps Why not?Why not?

Mutex method 2: lock varsMutex method 2: lock vars

►software methodsoftware method

►employs single, shared lock variable employs single, shared lock variable initially = 0initially = 0

►uses busy wait uses busy wait spin lock spin lock

Mutex method 2: lock varsMutex method 2: lock vars

shared int x=0;shared int x=0;//wait for lock//wait for lockwhile (x!=0) ; //while (x!=0) ; // note the empty note the empty

statementstatementx=1; //get lockx=1; //get lock//critical section//critical section……//end critical section//end critical sectionx=0; //release lockx=0; //release lock

►Doesn’t work (w/out hardware support).Doesn’t work (w/out hardware support).►What about performance?What about performance?

Mutex method 3: strict Mutex method 3: strict alternationalternation

Mutex method 3: strict Mutex method 3: strict alternationalternation

► SoftwareSoftware► Problem: violates process cooperation rule Problem: violates process cooperation rule

#3.#3. Because in strict alternation, a process can be Because in strict alternation, a process can be

blocked from entering its C.S. by a process NOT blocked from entering its C.S. by a process NOT in its C.S.in its C.S.

► In general, a process can’t be in it’s C.S. 2x In general, a process can’t be in it’s C.S. 2x in a row.in a row.

► The 2 processes must be running at about The 2 processes must be running at about the same speed.the same speed.

Mutex method 4: Peterson’s (sofware) soln.Mutex method 4: Peterson’s (sofware) soln.

Mutex method 4: Peterson’s Mutex method 4: Peterson’s (software) soln.(software) soln.

Mutex method 4: Peterson’s soln. Mutex method 4: Peterson’s soln. (software)(software)

Mutex method 4: Peterson’s Mutex method 4: Peterson’s (sofware) soln.(sofware) soln.

►Works, but suffers from busy wait.Works, but suffers from busy wait.

►Has been generalized to more than 2 Has been generalized to more than 2 processes (but the above is only for 2).processes (but the above is only for 2).

Mutex method 5: TSL Mutex method 5: TSL instructioninstruction

► TSL = Test and Set LockedTSL = Test and Set Locked► TSL RX, LOCKTSL RX, LOCK

RX = register; LOCK = memory locationRX = register; LOCK = memory location Step 1: read contents of LOCK into RXStep 1: read contents of LOCK into RX Step 2: sets LOCK to 1Step 2: sets LOCK to 1 Indivisible instruction (non interruptible)Indivisible instruction (non interruptible) Memory, not cacheMemory, not cache Locks memory bus (so other processors can’t Locks memory bus (so other processors can’t

access/change LOCK)access/change LOCK)

► IA32 xchg and lock instructionsIA32 xchg and lock instructions

Mutex method 5: TSL Mutex method 5: TSL instructioninstruction

Priority inversion problemPriority inversion problem

►an unexpected consequence of busy waitan unexpected consequence of busy wait

►given H (a high priority job), and L (low given H (a high priority job), and L (low priority job)priority job)

►scheduling algorithm: whenever H is scheduling algorithm: whenever H is ready to run, L is preempted and H is run.ready to run, L is preempted and H is run.

Priority inversion problemPriority inversion problem

H runs…H runs…

H blocks on I/OH blocks on I/O

I/O completesI/O completes

H runs …H runs …

H attempts to enter C.S.H attempts to enter C.S.

H busy waits forever!H busy waits forever!

L is ready to runL is ready to run

L runs …L runs …

L enters C.S. …L enters C.S. …

……

L is preemptedL is preempted

.

.

.

Using mutex (provided by Using mutex (provided by OS)OS)

►Simpler than semaphoreSimpler than semaphore

►Two states: locked or unlockedTwo states: locked or unlocked

►Functions:Functions: Declare mutex variableDeclare mutex variable Initialize mutex variable (just once)Initialize mutex variable (just once) lock ---> C.S. ---> unlocklock ---> C.S. ---> unlock

#include <errno.h>#include <errno.h>#include <pthread.h>#include <pthread.h>……pthread_mutex_t mutex; ///< declare globalpthread_mutex_t mutex; ///< declare global (i.e., not inside (i.e., not inside

of any function)of any function)

……

//perform this one-time initialization (usually in main)//perform this one-time initialization (usually in main)int ret = pthread_mutex_init( &::mutex, NULL );int ret = pthread_mutex_init( &::mutex, NULL );if (ret) { perror( "main: mutex init error" ); exit(-1); }if (ret) { perror( "main: mutex init error" ); exit(-1); }……

//lock in thread code//lock in thread coderet = pthread_mutex_lock( &::mutex );ret = pthread_mutex_lock( &::mutex );if (ret) { printf( "%d: mutex lock error \n", tp-if (ret) { printf( "%d: mutex lock error \n", tp-

>whoAmI ); }>whoAmI ); } //critical section here//critical section here//unlock in thread code//unlock in thread codepthread_mutex_unlock( &::mutex );pthread_mutex_unlock( &::mutex );

#include <#include <windowswindows.h>.h>……CRITICAL_SECTION g_cs;CRITICAL_SECTION g_cs;……

//perform this one-time initialization (usually in main)//perform this one-time initialization (usually in main)InitializeCriticalSection( &g_cs );InitializeCriticalSection( &g_cs );……

//lock in thread code//lock in thread codeEnterCriticalSection( &g_cs );EnterCriticalSection( &g_cs );

//critical section here//critical section here

//unlock in thread code//unlock in thread codeLeaveCriticalSection( &g_cs );LeaveCriticalSection( &g_cs );

Problem:Problem:

► Modify filter program to also determine Modify filter program to also determine overall min and max of input data.overall min and max of input data.

1.1. Can you do this with global variables?Can you do this with global variables?

2.2. Can you do this without global Can you do this without global variables?variables?

► Which method requires mutex?Which method requires mutex?

SemaphoresSemaphores

(Bounded) Producer-(Bounded) Producer-ConsumerConsumer

►A producer produces some item and A producer produces some item and stores it in a warehouse.stores it in a warehouse.

►A consumer consumes an item by A consumer consumes an item by removing an item from the warehouse.removing an item from the warehouse.

►Notes:Notes: The producer must pause production if The producer must pause production if

the warehouse fills up (bounded).the warehouse fills up (bounded). If the warehouse is empty, the consumer If the warehouse is empty, the consumer

must wait for something to be produced.must wait for something to be produced.

(Bounded(Bounded) )

producer-producer-consumerconsumerproblemproblem

Danger, Will Robinson (a shared variable)!

(Bounded) Producer-consumer (Bounded) Producer-consumer problemproblem

► Buffer is initially empty.Buffer is initially empty.► Consumer checks count. It’s 0.Consumer checks count. It’s 0.► Scheduler interrupts consumer (puts Scheduler interrupts consumer (puts

consumer on ready queue).consumer on ready queue).► Producer runs.Producer runs.

Insert data into buffer.Insert data into buffer. Count is 1 so producer wakes up consumer.Count is 1 so producer wakes up consumer. But consumer is not asleep just yet! (The But consumer is not asleep just yet! (The

scheduler interrupted it right before the call to scheduler interrupted it right before the call to sleep().)sleep().)

Producer keeps inserting data into buffer until it’s Producer keeps inserting data into buffer until it’s full. Then producer goes to sleep!full. Then producer goes to sleep!

► Scheduler runs consumer. Consumer thinks Scheduler runs consumer. Consumer thinks count=0 so it goes to sleep!count=0 so it goes to sleep!

► Both sleep forever!Both sleep forever!

SemaphoresSemaphores

► Invented by Dutch computer scientist Invented by Dutch computer scientist Edsger Dijkstra.Edsger Dijkstra.

► Two basic operations:Two basic operations:1.1. UpUp

► increments the value of the semaphoreincrements the value of the semaphore► historically denoted as V (also known as signal)historically denoted as V (also known as signal)

2.2. DownDown► decrements the value of the semaphoredecrements the value of the semaphore► P (also known as wait)P (also known as wait)

SemaphoresSemaphores

Types:Types:1.1. POSIXPOSIX

► Shared only among Shared only among threadsthreads..

2.2. WindowsWindows► Can be system-widesystem-wide..

3.3. System VSystem V► Can be shared according to user-group-other Can be shared according to user-group-other

(can be (can be system-widesystem-wide).).

Binary semaphores = mutexBinary semaphores = mutex

►Create semaphore and initialize it to 1.Create semaphore and initialize it to 1. 1 = unlocked1 = unlocked 0 = locked0 = locked

►Then to use this as a mutex:Then to use this as a mutex: downdown

►c.s.c.s.

upup

POSIX SEMAPHORESPOSIX SEMAPHORES

POSIX Semaphores POSIX Semaphores (shared among (shared among

threads only)threads only)

#include <semaphore.h>#include <semaphore.h>

1.1. int sem_init ( sem_t* sem, int pshared, int sem_init ( sem_t* sem, int pshared, unsigned int value );unsigned int value );

2.2. int sem_wait ( sem_t* sem );int sem_wait ( sem_t* sem );3.3. int sem_trywait ( sem_t* sem );int sem_trywait ( sem_t* sem );4.4. int sem_post ( sem_t* sem );int sem_post ( sem_t* sem );5.5. int sem_getvalue ( sem_t* sem, int* sval );int sem_getvalue ( sem_t* sem, int* sval );6.6. int sem_destroy ( sem_t* sem );int sem_destroy ( sem_t* sem );

POSIX SemaphoresPOSIX Semaphores

int sem_init ( sem_t* sem, int pshared, int sem_init ( sem_t* sem, int pshared, unsigned int value );unsigned int value );

initializeinitialize

pshared must be 0 on (some versions of) pshared must be 0 on (some versions of) LinuxLinux►semaphore is not shared by processessemaphore is not shared by processes

Value is initial value for semaphore.Value is initial value for semaphore.

POSIX SemaphoresPOSIX Semaphores

int sem_wait ( sem_t* sem );int sem_wait ( sem_t* sem ); down (if possible/blocking)down (if possible/blocking)

int sem_trywait ( sem_t* sem );int sem_trywait ( sem_t* sem ); nonblocking downnonblocking down

►Blocking?Blocking?

POSIX SemaphoresPOSIX Semaphores

int sem_post ( sem_t* sem );int sem_post ( sem_t* sem ); up (nonblocking)up (nonblocking)

int sem_getvalue ( sem_t* sem, int* int sem_getvalue ( sem_t* sem, int* sval );sval ); get the current semaphore valueget the current semaphore value

int sem_destroy ( sem_t* sem );int sem_destroy ( sem_t* sem ); finish using the semaphorefinish using the semaphore

WINDOWS SEMAPHORESWINDOWS SEMAPHORES

Windows SemaphoresWindows Semaphores

HANDLE WINAPI CreateSemaphore (HANDLE WINAPI CreateSemaphore (

__in_opt LPSECURITY_ATTRIBUTES __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,lpSemaphoreAttributes,

__in LONG lInitialCount,__in LONG lInitialCount,

__in LONG lMaximumCount,__in LONG lMaximumCount,

__in_opt LPCTSTR lpName__in_opt LPCTSTR lpName

););

DWORD WINAPI WaitForSingleObject (DWORD WINAPI WaitForSingleObject (

__in HANDLE hHandle,__in HANDLE hHandle,

__in DWORD dwMilliseconds__in DWORD dwMilliseconds

);); //decrements count by 1 //decrements count by 1

BOOL WINAPI ReleaseSemaphore (BOOL WINAPI ReleaseSemaphore (

__in HANDLE hSemaphore,__in HANDLE hSemaphore,

__in LONG lReleaseCount,__in LONG lReleaseCount,

__out_opt LPLONG lpPreviousCount__out_opt LPLONG lpPreviousCount

);); //increments count by //increments count by lReleaseCountlReleaseCount

BOOL WINAPI CloseHandle (BOOL WINAPI CloseHandle (

__in HANDLE hObject__in HANDLE hObject

););

SYSTEM V SEMAPHORESSYSTEM V SEMAPHORES

System V Semaphores System V Semaphores (system-wide)(system-wide)

#include <sys/types.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/sem.h>

1.1. int semget ( key_t key, int nsems, int semflg );int semget ( key_t key, int nsems, int semflg ); create/access existingcreate/access existing

2.2. int semctl ( int semid, int semnum, int cmd, ... int semctl ( int semid, int semnum, int cmd, ... );); delete from systemdelete from system

3.3. int semop ( int semid, struct sembuf* sops, int semop ( int semid, struct sembuf* sops, unsigned nsops );unsigned nsops ); used for used for upup and and downdown

Create/access existingCreate/access existing

//using the key, get the semaphore id//using the key, get the semaphore idconst int sid = semget( mySemKey, 1, IPC_CREAT | const int sid = semget( mySemKey, 1, IPC_CREAT |

0700 );0700 );

if (sid==-1) {if (sid==-1) { perror( "semget " );perror( "semget " ); exit( -1 );exit( -1 );}}printf( "sem id=%d \n", sid );printf( "sem id=%d \n", sid );

create if necessary

system-wide permissions

(In C/C++, octal values start with 0.)

system-wide unique number

Create/access existingCreate/access existing

//using the key, get the semaphore id//using the key, get the semaphore idconst int sid = semget( mySemKey, 1, IPC_CREAT | const int sid = semget( mySemKey, 1, IPC_CREAT |

0700 );0700 );

alternative (#include <sys/stat.h>):alternative (#include <sys/stat.h>):const int sid = semget( mySemKey, 1, IPC_CREAT | const int sid = semget( mySemKey, 1, IPC_CREAT |

S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTHS_IWOTH ); );

create if necessary

system-wide permissions

(In C/C++, octal values start with 0.)

Access and deleteAccess and delete

//using the key, get the semaphore id//using the key, get the semaphore idconst int sid = semget( mySemKey, 1, 0700 );const int sid = semget( mySemKey, 1, 0700 );

if (sid==-1) {if (sid==-1) { perror( "semget " );perror( "semget " ); exit( -1 );exit( -1 );}}printf( "sem id=%d \n", sid );printf( "sem id=%d \n", sid );

//delete the semaphore//delete the semaphoresemctl( sid, 0, IPC_RMID, 0 );semctl( sid, 0, IPC_RMID, 0 );

Down functionDown function

static void down ( const int whichSid ) {static void down ( const int whichSid ) { struct sembuf sem_lock;struct sembuf sem_lock;

sem_lock.sem_num = 0; //semaphore number: 0 = firstsem_lock.sem_num = 0; //semaphore number: 0 = first sem_lock.sem_op = -1; //semaphore operationsem_lock.sem_op = -1; //semaphore operation sem_lock.sem_flg = 0; //operation flagssem_lock.sem_flg = 0; //operation flags

if (semop(whichSid, &sem_lock, 1) == -1) {if (semop(whichSid, &sem_lock, 1) == -1) { perror("semop ");perror("semop "); exit(-1);exit(-1); }}}}

Up functionUp function

static void up ( const int whichSid ) {static void up ( const int whichSid ) { struct sembuf sem_unlock;struct sembuf sem_unlock;

sem_unlock.sem_num = 0; //semaphore number: 0 = firstsem_unlock.sem_num = 0; //semaphore number: 0 = first sem_unlock.sem_op = 1; //semaphore operationsem_unlock.sem_op = 1; //semaphore operation sem_unlock.sem_flg = 0; //operation flagssem_unlock.sem_flg = 0; //operation flags

if (semop(whichSid, &sem_unlock, 1) == -1) {if (semop(whichSid, &sem_unlock, 1) == -1) { perror("semop");perror("semop"); exit(-1);exit(-1); }}}}

Solution to (bounded) producer-consumer problem using semaphores (via up() and down()).

Note: 3 semaphores (one used as mutex)!

(BOUNDED) PRODUCER-(BOUNDED) PRODUCER-CONSUMER DEMOCONSUMER DEMO

bounded.h,bounded.h,

boundedProducer.cpp,boundedProducer.cpp,

boundedConsumer.cppboundedConsumer.cpp

UNBOUNDED PRODUCER-UNBOUNDED PRODUCER-CONSUMERCONSUMER

(Unbounded) producer-(Unbounded) producer-consumerconsumer

►Every time the producer process runs, Every time the producer process runs, it produces one item.it produces one item.

►Every time the consumer runs, it Every time the consumer runs, it consumes one item (or waits until one consumes one item (or waits until one is available, and then consumes it).is available, and then consumes it).

//unbounded producer//unbounded producerint main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) { //using the key, get the semaphore id//using the key, get the semaphore id const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 );const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); if (sid==-1) {if (sid==-1) { perror( "semget " );perror( "semget " ); exit( -1 );exit( -1 ); }} printf( "sem id=%d \n", sid );printf( "sem id=%d \n", sid );

puts( "producing" );puts( "producing" ); struct sembuf sem_unlock;struct sembuf sem_unlock; sem_unlock.sem_num = 0; //semaphore number: 0 = firstsem_unlock.sem_num = 0; //semaphore number: 0 = first sem_unlock.sem_op = 1; //semaphore operationsem_unlock.sem_op = 1; //semaphore operation sem_unlock.sem_flg = 0; //operation flagssem_unlock.sem_flg = 0; //operation flags

if (semop(sid, &sem_unlock, 1) == -1) {if (semop(sid, &sem_unlock, 1) == -1) { perror("semop ");perror("semop "); exit(-1);exit(-1); }} puts( "produced" );puts( "produced" );

return 0;return 0;}}

Unbounded producer basically does an up() to indicate production.

//consumer//consumerint main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) {

//using the key, get the semaphore id//using the key, get the semaphore id const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 );const int sid = semget( mySemKey, 1, IPC_CREAT | 0700 ); if (sid==-1) {if (sid==-1) { perror( "semget " );perror( "semget " ); exit( -1 );exit( -1 ); }} printf( "sem id=%d \n", sid );printf( "sem id=%d \n", sid );

puts( "consuming" );puts( "consuming" ); struct sembuf sem_lock;struct sembuf sem_lock; sem_lock.sem_num = 0; //semaphore number: 0 = firstsem_lock.sem_num = 0; //semaphore number: 0 = first sem_lock.sem_op = -1; //semaphore operationsem_lock.sem_op = -1; //semaphore operation sem_lock.sem_flg = 0; //operation flagssem_lock.sem_flg = 0; //operation flags if (semop(sid, &sem_lock, 1) == -1) {if (semop(sid, &sem_lock, 1) == -1) { perror("semop ");perror("semop "); exit(-1);exit(-1); }} puts( "consumed" );puts( "consumed" );

return 0;return 0;}}

Consumer basically does a down() to indicate consumption.

(UNBOUNDED) (UNBOUNDED) PRODUCER-CONSUMER PRODUCER-CONSUMER DEMODEMO

mySemKey.h,mySemKey.h,

producer.cpp, consumerWait.cpp, consumerNoWait.cpp, producer.cpp, consumerWait.cpp, consumerNoWait.cpp, bigProducer.cpp,bigProducer.cpp,

delete.cppdelete.cpp

Shared MemoryShared Memory

Shared memoryShared memory

►Shared memory operationsShared memory operations

shmgetshmget►allocates a shared memory segmentallocates a shared memory segment

shmctlshmctl►allows the user to receive information on a allows the user to receive information on a

shared memory segment, set the owner, shared memory segment, set the owner, group, and permissions of a shared memory group, and permissions of a shared memory segment, or destroy a segmentsegment, or destroy a segment

Shared memoryShared memory

►Shared memory operationsShared memory operations

shmatshmat►attaches the shared memory segment attaches the shared memory segment

(identified by shmid) to the address space of (identified by shmid) to the address space of the calling processthe calling process

shmdtshmdt►detaches the shared memory segment detaches the shared memory segment

(located at the address specified by shmaddr) (located at the address specified by shmaddr) from the address space of the calling processfrom the address space of the calling process

Shared memoryShared memory

►From the Linux sem_init man page:From the Linux sem_init man page: The pshared argument indicates whether this The pshared argument indicates whether this

semaphore is to be shared between the threads semaphore is to be shared between the threads of a process, or between processes.of a process, or between processes.

1.1. If pshared has the value 0, then the semaphore is If pshared has the value 0, then the semaphore is shared between the threadsshared between the threads of a process, and of a process, and should be should be located at some address that is visible to located at some address that is visible to all threadsall threads (e.g., a global variable, or a variable (e.g., a global variable, or a variable allocated dynamically on the heap).allocated dynamically on the heap).

2.2. If pshared is nonzero, then the semaphore is If pshared is nonzero, then the semaphore is shared between processesshared between processes, and should be , and should be located located in a region of shared memoryin a region of shared memory..

Memory mapped filesMemory mapped files

Memory mapped filesMemory mapped files

““There comes a time when you want to read and write to There comes a time when you want to read and write to and from files so that the information is shared and from files so that the information is shared between processes. Think of it this way: two between processes. Think of it this way: two processes both open the same file and both read and processes both open the same file and both read and write from it, thus sharing the information. The write from it, thus sharing the information. The problem is, sometimes it's a pain to do all those problem is, sometimes it's a pain to do all those fseek()s and stuff to get around. Wouldn't it be easier fseek()s and stuff to get around. Wouldn't it be easier if you could just map a section of the file to memory, if you could just map a section of the file to memory, and get a pointer to it? Then you could simply use and get a pointer to it? Then you could simply use pointer arithmetic to get (and set) data in the file.pointer arithmetic to get (and set) data in the file.

Well, this is exactly what a memory mapped file is. And Well, this is exactly what a memory mapped file is. And it's really easy to use, too. A few simple calls, mixed it's really easy to use, too. A few simple calls, mixed with a few simple rules, and you're mapping like a with a few simple rules, and you're mapping like a mad-person.”mad-person.”

http://beej.us/guide/ipc/mmap.htmlhttp://beej.us/guide/ipc/mmap.html

Memory mapped filesMemory mapped files

►mmapmmap

void* mmap ( void* start, size_t length, int void* mmap ( void* start, size_t length, int prot, int flags, int fd, off_t offset );prot, int flags, int fd, off_t offset );

map map lengthlength bytes starting at offset bytes starting at offset offsetoffset from the file specified by the file from the file specified by the file descriptor descriptor fdfd into memory, preferably at into memory, preferably at address address startstart

Memory mapped filesMemory mapped files

► munmapmunmap

int munmap ( void* start, size_t length );int munmap ( void* start, size_t length );

The munmap system call deletes the mappings for The munmap system call deletes the mappings for the specified address range, and causes further the specified address range, and causes further references to addresses within the range to generate references to addresses within the range to generate invalid memory references.invalid memory references.

The region is also automatically unmapped when the The region is also automatically unmapped when the process is terminated.process is terminated.

On the other hand, closing the file descriptor does not On the other hand, closing the file descriptor does not unmap the region.unmap the region.

Pipes and named Pipes and named pipespipes

PipesPipes

More PipesMore Pipes

Too many pipes!Too many pipes!

// Excerpt from "Linux Programmer's Guide - Chapter 6."// Excerpt from "Linux Programmer's Guide - Chapter 6."// (C)opyright 1994-1995, Scott Burkett// (C)opyright 1994-1995, Scott Burkett#include <stdio.h>#include <stdio.h>#include <unistd.h>#include <unistd.h>#include <sys/types.h>#include <sys/types.h>

int main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) { int fd[2], nbytes;int fd[2], nbytes; pid_t childpid;pid_t childpid; char string[] = "Hello, world!\n", readbuffer[80];char string[] = "Hello, world!\n", readbuffer[80]; pipe( fd );pipe( fd ); if (if ((childpid = fork())(childpid = fork()) == -1) { == -1) { perror( "fork" );perror( "fork" ); exit( 1 );exit( 1 ); }} if (childpid == 0) { //Child process closes up input side of pipeif (childpid == 0) { //Child process closes up input side of pipe close( fd[0] );close( fd[0] ); /* Send "string" through the output side of pipe *//* Send "string" through the output side of pipe */ write( fd[1], string, (strlen(string)+1) );write( fd[1], string, (strlen(string)+1) ); } else { //Parent process closes up output side of pipe} else { //Parent process closes up output side of pipe close( fd[1] );close( fd[1] ); /* Read in a string from the pipe *//* Read in a string from the pipe */ nbytes = read( fd[0], readbuffer, sizeof(readbuffer) );nbytes = read( fd[0], readbuffer, sizeof(readbuffer) ); printf( "parent: received string: %s", readbuffer );printf( "parent: received string: %s", readbuffer ); }} return 0;return 0;}}

Pipes via pipe()Pipes via pipe()

// Excerpt from "Linux Programmer's Guide - Chapter 6."// Excerpt from "Linux Programmer's Guide - Chapter 6."// (C)opyright 1994-1995, Scott Burkett// (C)opyright 1994-1995, Scott Burkett#include <stdio.h>#include <stdio.h>#define MAXSTRS 5#define MAXSTRS 5int main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) { FILE *pipe_fp;FILE *pipe_fp; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie",

"delta"};"delta"};

/* Create one way pipe line with call to popen() *//* Create one way pipe line with call to popen() */ if (if (( pipe_fp = popen("sort", "w"))( pipe_fp = popen("sort", "w")) == NULL) { == NULL) { perror("popen");perror("popen"); exit(1);exit(1); }} /* Processing loop *//* Processing loop */ for (int cntr=0; cntr<MAXSTRS; cntr++) {for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs(strings[cntr], fputs(strings[cntr], pipe_fppipe_fp);); fputc('\n', fputc('\n', pipe_fppipe_fp);); }} /* Close the pipe *//* Close the pipe */ pclose(pipe_fp);pclose(pipe_fp); return 0;return 0;}}

Pipes via Pipes via popen()popen()

Any valid shell command.

Can be “w” or “r”.

// Excerpt from "Linux Programmer's Guide - Chapter 6"// Excerpt from "Linux Programmer's Guide - Chapter 6"// (C)opyright 1994-1995, Scott Burkett// (C)opyright 1994-1995, Scott Burkett#include <stdio.h>#include <stdio.h>#define MAXSTRS 5#define MAXSTRS 5int main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) { FILE *pipe_fp;FILE *pipe_fp; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie",

"delta"};"delta"};

/* Create one way pipe line with call to popen() *//* Create one way pipe line with call to popen() */ if (if (( pipe_fp = popen("sort", "w"))( pipe_fp = popen("sort", "w")) == NULL) { == NULL) { perror("popen");perror("popen"); exit(1);exit(1); }} /* Processing loop *//* Processing loop */ for (int cntr=0; cntr<MAXSTRS; cntr++) {for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs(strings[cntr], fputs(strings[cntr], pipe_fppipe_fp);); fputc('\n', fputc('\n', pipe_fppipe_fp);); }} /* Close the pipe *//* Close the pipe */ pclose(pipe_fp);pclose(pipe_fp); return 0;return 0;}}

Pipes via popen()Pipes via popen()

Any valid shell command.

Can be “w” or “r”.

How would I modify this to have obtain the sorted information?

// Excerpt from "Linux Programmer's Guide - Chapter 6"// Excerpt from "Linux Programmer's Guide - Chapter 6"// (C)opyright 1994-1995, Scott Burkett// (C)opyright 1994-1995, Scott Burkett#include <stdio.h>#include <stdio.h>#define MAXSTRS 5#define MAXSTRS 5int main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) { FILE *pipe_fp;FILE *pipe_fp; char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie", char *strings[MAXSTRS] = { "echo", "bravo", "alpha", "charlie",

"delta"};"delta"};

/* Create one way pipe line with call to popen() *//* Create one way pipe line with call to popen() */ if (( pipe_fp = popen("sort > junk.dat", "w")) == NULL) {if (( pipe_fp = popen("sort > junk.dat", "w")) == NULL) { perror("popen");perror("popen"); exit(1);exit(1); }} /* Processing loop *//* Processing loop */ for (int cntr=0; cntr<MAXSTRS; cntr++) {for (int cntr=0; cntr<MAXSTRS; cntr++) { fputs(strings[cntr], pipe_fp);fputs(strings[cntr], pipe_fp); fputc('\n', pipe_fp);fputc('\n', pipe_fp); }} /* Close the pipe *//* Close the pipe */ pclose(pipe_fp);pclose(pipe_fp); return 0;return 0;}}

Pipes via popen()Pipes via popen()

Any valid shell command.

Can be “w” or “r”.

How would I modify this to have obtain the sorted information?

Better but is junk.dat unique?

Named pipesNamed pipes

►Named pipesNamed pipes Use mkfifo command. (What is a FIFO?)Use mkfifo command. (What is a FIFO?) ExampleExample

►mkfifo mypipemkfifo mypipe► ls –l mypipels –l mypipe

pprw------- 1 ggrevera ggrevera 0 Oct 5 21:30 mypiperw------- 1 ggrevera ggrevera 0 Oct 5 21:30 mypipe

► ls –l > mypipels –l > mypipe Hangs! Why?Hangs! Why? Ctrl-cCtrl-c

► ls –l > mypipe &ls –l > mypipe &►cat < mypipecat < mypipe

Doesn’t hang! Why?Doesn’t hang! Why?

Named pipesNamed pipes

►Named pipesNamed pipes Use mkfifo command. (What is a FIFO?)Use mkfifo command. (What is a FIFO?) ExampleExample

►mkfifo mypipemkfifo mypipe► ls –l mypipels –l mypipe

pprw------- 1 ggrevera ggrevera 0 Oct 5 21:30 mypiperw------- 1 ggrevera ggrevera 0 Oct 5 21:30 mypipe

► ls –l > mypipels –l > mypipe Hangs! Why? Because it waits for the reader.Hangs! Why? Because it waits for the reader. Ctrl-cCtrl-c

► ls –l > mypipe &ls –l > mypipe &►cat < mypipecat < mypipe

Doesn’t hang! Why? Because the reader executes.Doesn’t hang! Why? Because the reader executes. Output on next slide.Output on next slide.

Output from named pipe Output from named pipe exampleexample

► ls –l > mypipe &ls –l > mypipe &► cat < mypipecat < mypipe

total 106412total 106412-rwx------ 1 ggrevera ggrevera 14215 Oct 5 20:45 a.out-rwx------ 1 ggrevera ggrevera 14215 Oct 5 20:45 a.outdrwx------ 5 ggrevera ggrevera 4096 Feb 3 2006 csc4025drwx------ 5 ggrevera ggrevera 4096 Feb 3 2006 csc4025drwx------ 4 ggrevera ggrevera 4096 Oct 3 09:59 csc4035drwx------ 4 ggrevera ggrevera 4096 Oct 3 09:59 csc4035-rw------- 1 ggrevera ggrevera 194560 Sep 6 12:52 csc4035.tar-rw------- 1 ggrevera ggrevera 194560 Sep 6 12:52 csc4035.tar-rw------- 1 ggrevera ggrevera 891 Dec 4 2005 dir.cpp-rw------- 1 ggrevera ggrevera 891 Dec 4 2005 dir.cpp......-rw------- 1 ggrevera ggrevera 283 Oct 5 20:44 sig.cpp-rw------- 1 ggrevera ggrevera 283 Oct 5 20:44 sig.cpp

[1]+ Done ls -l >mypipe[1]+ Done ls -l >mypipe

Why did this finish? Because the reader read everything.Why did this finish? Because the reader read everything.

SocketsSockets

SocketsSockets

Sockets – client-sideSockets – client-side

Steps:Steps:1.1. socket()socket()

creates an endpoint for communication and creates an endpoint for communication and returns a descriptorreturns a descriptor

2.2. connect()connect() attempts to make a connection to another attempts to make a connection to another

socketsocket

3.3. call read() and/or write()call read() and/or write() similar to an ordinary filesimilar to an ordinary file

#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#include <string.h>#include <string.h>#include <sys/types.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/in.h>#include <netdb.h>#include <netdb.h>#include <unistd.h>#include <unistd.h>

static void error ( char* msg ) {static void error ( char* msg ) { perror( msg );perror( msg ); exit( 0 );exit( 0 );}}

int main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) {

if (argc < 3) {if (argc < 3) { fprintf( stderr, "usage: %s hostname port \n", argv[0] );fprintf( stderr, "usage: %s hostname port \n", argv[0] ); exit( 0 );exit( 0 ); }} int portno = atoi( argv[2] );int portno = atoi( argv[2] ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 );int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) error( "ERROR opening socket“ );if (sockfd < 0) error( "ERROR opening socket“ );......

Sockets – client-sideSockets – client-side(writes a message and reads a (writes a message and reads a

response)response)

Sockets – client-sideSockets – client-side...... struct hostent* server = gethostbyname( argv[1] ); //does host exist?struct hostent* server = gethostbyname( argv[1] ); //does host exist? if (server == NULL) {if (server == NULL) { fprintf( stderr, "ERROR, no such host \n" );fprintf( stderr, "ERROR, no such host \n" ); exit( 0 );exit( 0 ); }}

struct sockaddr_in serv_addr;struct sockaddr_in serv_addr; bzero( &serv_addr, sizeof(serv_addr) ); //move 0’s to bufferbzero( &serv_addr, sizeof(serv_addr) ); //move 0’s to buffer serv_addr.sin_family = AF_INET;serv_addr.sin_family = AF_INET; //copy binary data from buffer to buffer//copy binary data from buffer to buffer bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length

);); serv_addr.sin_port = htons( portno ); //host byte order to network b.o.serv_addr.sin_port = htons( portno ); //host byte order to network b.o. if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) <

0)0) error( "ERROR connecting“ );error( "ERROR connecting“ );......

Sockets – client-sideSockets – client-side...... printf("Please enter the message: ");printf("Please enter the message: "); char buffer[256];char buffer[256]; bzero( buffer, sizeof(buffer) );bzero( buffer, sizeof(buffer) ); fgets( buffer, sizeof(buffer)-1, stdin );fgets( buffer, sizeof(buffer)-1, stdin ); int n = write( sockfd, buffer, strlen(buffer) );int n = write( sockfd, buffer, strlen(buffer) ); if (n < 0)if (n < 0) error("ERROR writing to socket");error("ERROR writing to socket"); bzero( buffer, sizeof(buffer) );bzero( buffer, sizeof(buffer) ); n = read( sockfd, buffer, sizeof(buffer)-1 );n = read( sockfd, buffer, sizeof(buffer)-1 ); if (n < 0) error("ERROR reading from socket");if (n < 0) error("ERROR reading from socket"); printf( "%s \n", buffer );printf( "%s \n", buffer );

return 0;return 0;}}

Sockets – client-side Sockets – client-side (complete code)(complete code)

#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#include <string.h>#include <string.h>#include <sys/types.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/in.h>#include <netdb.h>#include <netdb.h>#include <unistd.h>#include <unistd.h>

static void error ( char* msg ) {static void error ( char* msg ) { perror( msg );perror( msg ); exit( 0 );exit( 0 );}}

int main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) {

if (argc < 3) {if (argc < 3) { fprintf( stderr, "usage: %s hostname port \n", argv[0] );fprintf( stderr, "usage: %s hostname port \n", argv[0] ); exit( 0 );exit( 0 ); }} int portno = atoi( argv[2] );int portno = atoi( argv[2] ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 );int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); if (sockfd < 0) error("ERROR opening socket");if (sockfd < 0) error("ERROR opening socket"); struct hostent* server = gethostbyname(argv[1]);struct hostent* server = gethostbyname(argv[1]); if (server == NULL) {if (server == NULL) { fprintf( stderr, "ERROR, no such host \n" );fprintf( stderr, "ERROR, no such host \n" ); exit( 0 );exit( 0 ); }}

struct sockaddr_in serv_addr;struct sockaddr_in serv_addr; bzero( &serv_addr, sizeof(serv_addr) );bzero( &serv_addr, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET;serv_addr.sin_family = AF_INET; bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length );bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length ); serv_addr.sin_port = htons( portno );serv_addr.sin_port = htons( portno ); if (connect(sockfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)if (connect(sockfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0) error("ERROR connecting");error("ERROR connecting"); printf("Please enter the message: ");printf("Please enter the message: "); char buffer[256];char buffer[256]; bzero( buffer, sizeof(buffer) );bzero( buffer, sizeof(buffer) ); fgets( buffer, sizeof(buffer)-1, stdin );fgets( buffer, sizeof(buffer)-1, stdin ); int n = write(sockfd,buffer,strlen(buffer));int n = write(sockfd,buffer,strlen(buffer)); if (n < 0)if (n < 0) error("ERROR writing to socket");error("ERROR writing to socket"); bzero( buffer, sizeof(buffer) );bzero( buffer, sizeof(buffer) ); n = read( sockfd, buffer, sizeof(buffer)-1 );n = read( sockfd, buffer, sizeof(buffer)-1 ); if (n < 0) error("ERROR reading from socket");if (n < 0) error("ERROR reading from socket"); printf( "%s \n", buffer );printf( "%s \n", buffer );

return 0;return 0;}}

Sockets – server-sideSockets – server-side

Sockets – server-sideSockets – server-sideSteps:Steps:

1.1. socket()socket() creates an endpoint for communication and returns a creates an endpoint for communication and returns a

descriptordescriptor

2.2. bind()bind() this is called "assigning a name to a socket“this is called "assigning a name to a socket“ when a socket is created with socket, it exists in a when a socket is created with socket, it exists in a

name space (address family) but has no name name space (address family) but has no name assignedassigned

3.3. listen()listen() To accept connections, a socket is first created To accept connections, a socket is first created

with socket(), a willingness to accept incoming with socket(), a willingness to accept incoming connections and a queue limit for incoming connections and a queue limit for incoming connections are specified with listen, and then the connections are specified with listen, and then the connections are accepted with accept().connections are accepted with accept().

4.4. Repeat forever:Repeat forever:1.1. accept()accept()2.2. fork() a child process that performs reads and/or fork() a child process that performs reads and/or

writes as per ordinary file.writes as per ordinary file.

int accept ( int s, struct sockaddr* int accept ( int s, struct sockaddr* addr, socklen_t* addrlen );addr, socklen_t* addrlen );

► It extracts the first connection request It extracts the first connection request on the queue of pending connections, on the queue of pending connections, creates a new connected socket with creates a new connected socket with mostly the same properties as s, and mostly the same properties as s, and allocates a new file descriptor for the allocates a new file descriptor for the socket, which is returned.socket, which is returned.

►The newly created socket is no longer The newly created socket is no longer in the listening state. The original in the listening state. The original socket s is unaffected by this call.socket s is unaffected by this call.

/**/** * \file server2.cpp* \file server2.cpp * \author george j. grevera* \author george j. grevera * \brief A simple server in the internet domain using TCP. Runs on* \brief A simple server in the internet domain using TCP. Runs on * polaris (but not on scott).* polaris (but not on scott). * To compile: g++ -o server2.exe server2.cpp -lsocket* To compile: g++ -o server2.exe server2.cpp -lsocket */*/#include <assert.h>#include <assert.h>#include <netinet/in.h>#include <netinet/in.h>#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#include <string.h>#include <string.h>#include <sys/socket.h>#include <sys/socket.h>#include <unistd.h>#include <unistd.h>

static const int Port = 8090;static const int Port = 8090;static const bool Verbose = true;static const bool Verbose = true;//----------------------------------------------------------------------//----------------------------------------------------------------------int main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) {

//create an endpoint for communication//create an endpoint for communication if (Verbose) puts( "socket()" );if (Verbose) puts( "socket()" ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 );int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); assert( sockfd != -1 );assert( sockfd != -1 );……

Sockets – server-Sockets – server-sideside

……

//assign a name to the socket//assign a name to the socket

struct sockaddr_in serv_addr;struct sockaddr_in serv_addr;

memset( &serv_addr, 0, sizeof(serv_addr) );memset( &serv_addr, 0, sizeof(serv_addr) );

serv_addr.sin_family = AF_INET;serv_addr.sin_family = AF_INET;

serv_addr.sin_addr.s_addr = INADDR_ANY;serv_addr.sin_addr.s_addr = INADDR_ANY;

serv_addr.sin_port = htons( Port );serv_addr.sin_port = htons( Port );

if (Verbose) printf( "bind() port %d. \n", Port );if (Verbose) printf( "bind() port %d. \n", Port );

int ret = bind( sockfd, (struct sockaddr*)&serv_addr, int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) );sizeof(serv_addr) );

assert( ret != -1 );assert( ret != -1 );

……

Sockets – server-Sockets – server-sideside

…… //a willingness to accept incoming connections and a queue//a willingness to accept incoming connections and a queue // limit for incoming connections are specified with listen// limit for incoming connections are specified with listen if (Verbose) puts( "listen()" );if (Verbose) puts( "listen()" ); ret = listen( sockfd, 5 );ret = listen( sockfd, 5 ); assert( ret != -1 );assert( ret != -1 );

……

Sockets – server-Sockets – server-sideside

……

for ( ; ; ) {for ( ; ; ) {

//extract the first connection request on the queue of pending connections, create a new connected //extract the first connection request on the queue of pending connections, create a new connected socket withsocket with

// mostly the same properties as s, and allocate a new file descriptor for the socket, which is returned// mostly the same properties as s, and allocate a new file descriptor for the socket, which is returned

if (Verbose) puts( "parent: accept()" );if (Verbose) puts( "parent: accept()" );

struct sockaddr_in cli_addr;struct sockaddr_in cli_addr;

socklen_t clilen = sizeof( cli_addr );socklen_t clilen = sizeof( cli_addr );

int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 );assert( newsockfd != -1 );

if (Verbose) puts( "parent: fork()" );if (Verbose) puts( "parent: fork()" );

int pid = fork();int pid = fork();

if (pid==0) {if (pid==0) {

if (Verbose) puts( "child: after fork()" );if (Verbose) puts( "child: after fork()" );

close( sockfd );close( sockfd );

char buffer[ 256 ];char buffer[ 256 ];

memset( buffer, 0, sizeof(buffer) );memset( buffer, 0, sizeof(buffer) );

puts( "child: read()" );puts( "child: read()" );

int n = read( newsockfd, buffer, sizeof(buffer)-1 );int n = read( newsockfd, buffer, sizeof(buffer)-1 );

assert( n != -1 );assert( n != -1 );

printf( "child: Here is the message: %s\n", buffer );printf( "child: Here is the message: %s\n", buffer );

puts( "child: write()" );puts( "child: write()" );

n = write( newsockfd, "I got your message", strlen("I got your message") );n = write( newsockfd, "I got your message", strlen("I got your message") );

assert( n != -1 );assert( n != -1 );

close( newsockfd );close( newsockfd );

exit( 0 );exit( 0 );

}}

close( newsockfd );close( newsockfd );

}}

return 0;return 0;

}}

Sockets – server-Sockets – server-sideside

Sockets – server-side Sockets – server-side (complete code)(complete code)

/**/** * \file server2.cpp* \file server2.cpp * \author george j. grevera* \author george j. grevera * \brief A simple server in the internet domain using TCP. Runs on* \brief A simple server in the internet domain using TCP. Runs on * polaris (but not on scott).* polaris (but not on scott). * To compile: g++ -o server2.exe server2.cpp -lsocket* To compile: g++ -o server2.exe server2.cpp -lsocket */*/#include <assert.h>#include <assert.h>#include <netinet/in.h>#include <netinet/in.h>#include <stdio.h>#include <stdio.h>#include <stdlib.h>#include <stdlib.h>#include <string.h>#include <string.h>#include <sys/socket.h>#include <sys/socket.h>#include <unistd.h>#include <unistd.h>

static const int Port = 8090;static const int Port = 8090;static const bool Verbose = true;static const bool Verbose = true;//----------------------------------------------------------------------//----------------------------------------------------------------------int main ( int argc, char* argv[] ) {int main ( int argc, char* argv[] ) {

//create an endpoint for communication//create an endpoint for communication if (Verbose) puts( "socket()" );if (Verbose) puts( "socket()" ); int sockfd = socket( AF_INET, SOCK_STREAM, 0 );int sockfd = socket( AF_INET, SOCK_STREAM, 0 ); assert( sockfd != -1 );assert( sockfd != -1 );

//assign a name to the socket//assign a name to the socket struct sockaddr_in serv_addr;struct sockaddr_in serv_addr; memset( &serv_addr, 0, sizeof(serv_addr) );memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET;serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY;serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons( Port );serv_addr.sin_port = htons( Port ); if (Verbose) printf( "bind() port %d. \n", Port );if (Verbose) printf( "bind() port %d. \n", Port ); int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) );int ret = bind( sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ); assert( ret != -1 );assert( ret != -1 );

//a willingness to accept incoming connections and a queue//a willingness to accept incoming connections and a queue // limit for incoming connections are specified with listen// limit for incoming connections are specified with listen if (Verbose) puts( "listen()" );if (Verbose) puts( "listen()" ); ret = listen( sockfd, 5 );ret = listen( sockfd, 5 ); assert( ret != -1 );assert( ret != -1 );

for ( ; ; ) {for ( ; ; ) { //extract the first connection request on the queue of//extract the first connection request on the queue of // pending connections, create a new connected socket with// pending connections, create a new connected socket with // mostly the same properties as s, and allocate a new file// mostly the same properties as s, and allocate a new file // descriptor for the socket, which is returned// descriptor for the socket, which is returned if (Verbose) puts( "parent: accept()" );if (Verbose) puts( "parent: accept()" ); struct sockaddr_in cli_addr;struct sockaddr_in cli_addr; socklen_t clilen = sizeof( cli_addr );socklen_t clilen = sizeof( cli_addr ); int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen );int newsockfd = accept( sockfd, (struct sockaddr*)&cli_addr, &clilen ); assert( newsockfd != -1 );assert( newsockfd != -1 );

if (Verbose) puts( "parent: fork()" );if (Verbose) puts( "parent: fork()" ); int pid = fork();int pid = fork(); if (pid==0) {if (pid==0) { if (Verbose) puts( "child: after fork()" );if (Verbose) puts( "child: after fork()" ); close( sockfd );close( sockfd );

char buffer[ 256 ];char buffer[ 256 ]; memset( buffer, 0, sizeof(buffer) );memset( buffer, 0, sizeof(buffer) ); puts( "child: read()" );puts( "child: read()" ); int n = read( newsockfd, buffer, sizeof(buffer)-1 );int n = read( newsockfd, buffer, sizeof(buffer)-1 ); assert( n != -1 );assert( n != -1 );

printf( "child: Here is the message: %s\n", buffer );printf( "child: Here is the message: %s\n", buffer ); puts( "child: write()" );puts( "child: write()" ); n = write( newsockfd, "I got your message",n = write( newsockfd, "I got your message", strlen("I got your message") );strlen("I got your message") ); assert( n != -1 );assert( n != -1 );

close( newsockfd );close( newsockfd ); exit( 0 );exit( 0 ); }} close( newsockfd );close( newsockfd ); }}

return 0;return 0;}}//----------------------------------------------------------------------//----------------------------------------------------------------------

Message queuesMessage queues

Message queuesMessage queues

#include <sys/types.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/ipc.h>#include <sys/msg.h>#include <sys/msg.h>

► MSGMAX defines the max length of a message (~8K).MSGMAX defines the max length of a message (~8K).

► Define your message(s).Define your message(s). You may define many different messages of different lengths.You may define many different messages of different lengths.

struct myMessage {struct myMessage {long mtype;long mtype; //message type//message type…… //body of message (you decide)//body of message (you decide)

};};

Message queuesMessage queues

►msgget - begin accessing (and create if msgget - begin accessing (and create if necessary) a message queuenecessary) a message queueint msgget ( key_t key, int msgflg );int msgget ( key_t key, int msgflg );

►msgsnd - send (enqueue) a messagemsgsnd - send (enqueue) a messageint msgsnd ( int msqid, struct msgbuf* msgp,int msgsnd ( int msqid, struct msgbuf* msgp,

size_t msgsz, int msgflg );size_t msgsz, int msgflg );

►msgrcv - receive (dequeue) a messagemsgrcv - receive (dequeue) a messagessize_t msgrcv ( int msqid, struct msgbuf* msgp,ssize_t msgrcv ( int msqid, struct msgbuf* msgp,

size_t msgsz, long msgtyp, int msgflg );size_t msgsz, long msgtyp, int msgflg );

►msgctl - misc. message queue controlmsgctl - misc. message queue control

Other IPC mechanisms:Other IPC mechanisms:

►MonitorsMonitors A collection of A collection of

procedures, variables, procedures, variables, and data structures that and data structures that are all grouped together are all grouped together in a special kind of in a special kind of module or package.module or package.

Only one process can be Only one process can be active in a monitor at active in a monitor at any instant.any instant.

Monitors and the (bounded) Monitors and the (bounded) producer-consumer problemproducer-consumer problem

Other IPC mechanisms:Other IPC mechanisms:

►MonitorsMonitors►Message passing (MPI)Message passing (MPI)►BarriersBarriers