62
cs431-cotter 1 Linux Process Linux Process Synchronization Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess Communications in Linux - Gray

Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

Embed Size (px)

Citation preview

Page 1: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 1

Linux Process Linux Process SynchronizationSynchronization

• Tanenbaum 10.3, 2.3• Linux man pthread_mutex_init, etc.

• The Linux Programming Interface - Kerrisk• Interprocess Communications in Linux - Gray

Page 2: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 2cs431-cotter

Overview

• Linux IPC• Signal• Alarm• Wait• Semaphore (named and unnamed)• Mutex• Pipe ( named and unnamed)• Messages• Shared Memory

Page 3: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 3

Linux IPCLinux IPC

• Kernel Synchronization– Use wait_queue for kernel process sync– Allows multiple processes to wait for a single event– Serves as basic component to build user process sync

• Process synchronization– Signal - most primitive– Semaphore– Pipes– etc.

Page 4: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 4

Figure 10-5. The signals required by POSIX.

Signals in Linux

Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall, Inc. All rights reserved. 0-13-6006639

Page 5: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 5

SignalsSignals

1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL

5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE

9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS

13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGURG

17) SIGSTOP 18) SIGTSTP 19) SIGCONT 20) SIGCHLD

21) SIGTTIN 22) SIGTTOU 23) SIGIO 24) SIGXCPU

25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH

29) SIGINFO 30) SIGUSR1 31) SIGUSR2

Current versions of Linux support 64 signals (real time signals added).

See: man 2 signal, man 2 sigaction man 7 signal

Page 6: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 6

Signal Handler

• Signal function can have different behavior based on the version of UNIX.

• sigaction (signal_to_catch, new_action, old_action)• struct sigaction {

void * sa_handler; // What function do we call?

sigset_t mask; // Mask of signals to block when called

int sa_flags; // Special flags to set.

};

Page 7: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 7

AlarmAlarm

• Allows user program to set an external timer (measured in seconds).

• If alarm times out, sigalrm will be sent to the calling process.

• Use: sigaction (SIGALRM, sigaction, NULL);

Page 8: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 8

Sig_alarm.cpp#include <iostream>#include <signal.h>#include <stdlib.h>#include <string.h>using namespace std;

#define MAXLINE 128static void sig_alarm(int signo);

int main () {int n;char line [MAXLINE];struct sigaction act;memset (&act, 0, sizeof(act));act.sa_handler = &sig_alarm;act.sa_flags = SA_RESTART;

Page 9: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 9

Sig_alarm.cpp

if ((sigaction(SIGALRM, &act, NULL)) < 0) {cout <<"The sigact function returned an error" <<

endl; exit (1);}alarm (5);if ( cin.getline(line, MAXLINE) < 0) {

cout << "cin returned an error" << endl;exit(1);}alarm(0);cout << line << endl;exit(0);

}

static void sig_alarm(int signo) {cout << " ### We got the alarm signal!! ###" << endl;

}

Page 10: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 10

sig_alarm.cpp Outputsig_alarm.cpp Output

[rcotter@kc-sce-450p2 cs431]$ g++ -o sigtest sig_alarm3.cpp

[rcotter@kc-sce-450p2 cs431]$ ./sigtest

This is a test

This is a test

[rcotter@kc-sce-450p2 cs431]$ ./sigtest

This is another ### We got the alarm signal!! ###

test

This is another test

[rcotter@kc-sce-450p2 cs431]$

Page 11: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 11

wait( )wait( )#include <sys/types.h>

#include <sys/wait.h>

pid_t wait (int *status);

• The wait function suspends execution of the current pro cess until a child has exited, or until a signal is deliv ered whose action is to terminate the current process or to call a signal handling function. If a child has already exited by the time of the call (a so-called "zom bie" process), the function returns immediately. Any sys tem resources used by the child are freed.

Page 12: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 12

waittest1.cwaittest1.c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>

int main(){

pid_t pid;int status;

printf("Forking child process...\n");if ((pid = fork()) < 0){

printf("fork failed!\n");exit(1);

}

Page 13: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 13

waittest1.cwaittest1.celse if (pid == 0) { /* child process */

sleep(5);printf("Child process is shutting down\n");exit(7);

}else { /* parent process */

if (wait (&status) != pid) {printf("Wait returned invalid pid\n");exit(1);

}if (WIFEXITED(status))

printf("Normal Termination. Exit value %2d\n",WEXITSTATUS(status));

else {printf("Abnormal termination!!!\n");exit(1);

}printf("Parent shutting down...\n");exit(0);

}}

Page 14: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 14

waittest.c outputwaittest.c output

rcotter@debian-alpha:~$ gcc -o waittest waittest1.c

rcotter@debian-alpha:~$ ./waittest

Forking child process...

Child process is shutting down

Normal Termination. Exit value 7

Parent shutting down...

rcotter@debian-alpha:~$

Page 15: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 15

SemaphoresSemaphores

• POSIX version of semaphores– #include <semaphore.h>– classic semaphore implementation

• System V version of semaphores– #include <sys/sem.h>– Enhanced version of semaphores to include

sets

Page 16: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 16

POSIX (unnamed) SemaphoresPOSIX (unnamed) Semaphores

• sem_t empty, full;

• int sem_init ((sem_t *sem, int pshared, unsigned int value));– sem_t (address of semaphore to be initialized– pshared (is semaphore shared?) SHARED, 0– initial value

• int sem_wait ((sem_t *sem));– sem_t (address of semaphore to be waited for)

• int sem_post ((sem_t *sem));– sem_t (address of semaphore to be signalled)

Page 17: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 17

Example Semaphore fragmentExample Semaphore fragmentsem_t checker;

Main Program {declare variables...sem_init(&checker, 0, 1);pthread_create(&pid1, NULL, job, NULL);pthread_create(&pid2, NULL, job, NULL);pthread_join(pid1, NULL);pthread_join(pid2, NULL);:

}job() { while (work to do..) {

sem_wait (&checker);do stuff...sem_post(&checker);do other stuff....

}}

Page 18: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

18cs431-cottercs431-cotter 1818

POSIX Named Semaphores• sem_t empty, full; • sem_t *sem_open (char *name, int oflag, [mode_t mode[, [int init_value]);– char *name (must begin with “/”)– [O_CREAT], [O_EXCL], 0 (new or existing semaphore?)– mode (if new, mod bits 0xxx)– Init_value (if new, initial value of semaphore)

• int sem_wait ((sem_t *sem));– sem_t (address of semaphore to be waited for)

• int sem_post ((sem_t *sem));– sem_t (address of semaphore to be signalled)

• int sem_close (sem_t *sem);• int sem_unlink(char *name);• int sem_getvalue (sem_t *sem, int *val);• Named semaphore has kernel persistence

– Created in /dev/shm

Page 19: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

19

Named Semaphore exampleproducer - Consumer

#define SHARED 0#define BUFSIZE 20

int terminatethreads=0;

void *Producer(void *); /* the two threads */void *Consumer(void *);

sem_t *Sempty, *Sfull, *Sflag; /* the semaphore descriptors */char sem1[] = "/semEmpty"; //The names for the semaphoreschar sem2[] = "/semFull";char sem3[] = "/semFlag";int buf[BUFSIZE]; /* shared buffer */int mycount;

static void sig_alarm(int signo);

Page 20: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

20

Named Semaphore exampleint main(int argc, char *argv[]) { int ans; time_t now; pthread_t pid, cid; time (&now); srand (now); if (signal (SIGALRM, sig_alarm) == SIG_ERR) {

cout << "The signal function returned an error" << endl;exit (1);

} //Here we set the alarm to specified seconds. alarm (atoi(argv[1])); cout << “Alarm set. Now for semaphores" << endl;

Sflag = sem_open (sem3, O_CREAT, 660, 1); Sfull = sem_open (sem2, O_CREAT, 660, 0); Sempty = sem_open (sem1, O_CREAT, 660, BUFSIZE); mycount = 0;

Page 21: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

21

Named Semaphore example cout << "main started" << endl; pthread_create(&pid, 0, Producer, NULL); pthread_create(&cid, 0, Consumer, NULL); cout << "Created both threads" << endl; pthread_join(pid, NULL); pthread_join(cid, NULL); cout << "The number of items still in the buffer is " << mycount << endl; sem_getvalue(Sfull, &ans); cout << “The value of Sfull is “ << ans << endl; sem_close(Sflag); sem_close(Sfull); sem_close(Sempty); sem_unlink(sem1); sem_unlink(sem2); sem_unlink(sem3); cout << "Main done\n" << endl; return 0;}

Page 22: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

22

Named Semaphore examplevoid *Producer(void *arg) { int produced=0; int input = 0; cout << "\nProducer created.." << endl; while(!terminatethreads) { sem_wait(Sempty); //Decrements 'empty'

produced++;input = (input + 1) % BUFSIZE;

sem_wait(Sflag); buf[input] = produced; mycount++; sem_post (Sflag);

cout << "Producing widget # " << produced << " in buffer # " << input << endl;

sem_post(Sfull);//increments full , tell consumer that it can consume nowusleep(rand () %997);

} return &buf[0];}

Page 23: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

23

Named Semaphore examplevoid *Consumer(void *arg) { int consumed= 0; cout << "\nConsumer created.." << endl; while(!terminatethreads) {

sem_wait(Sfull);consumed = (consumed + 1) % BUFSIZE;sem_wait(Sflag);mycount--;sem_post(Sflag);

cout << "Consuming widget # " << buf[consumed] << " in buffer # " << consumed << endl;sem_post(Sempty);usleep(rand () %1003);

} return &buf[0];}

static void sig_alarm(int signo) { cout << "\nWe got the Signal Alarm, Terminating the threads...\n"<< endl;

terminatethreads=1; return;}

Page 24: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 24

Figure 2-30. Some of the Pthreads calls relating to mutexes.

Mutexes in Pthreads (1)

Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall, Inc. All rights reserved. 0-13-6006639

Page 25: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 25

Figure 2-31. Some of the Pthreads calls relating to condition variables.

Mutexes in Pthreads (2)

Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall, Inc. All rights reserved. 0-13-6006639

Page 26: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 26

Figure 2-32. Using threads to solve

the producer-consumer problem.

Mutexes in Pthreads (3)

Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall, Inc. All rights reserved. 0-13-6006639

Page 27: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

27

Linux Interprocess Communications

• Unnamed Pipes

• Named Pipes

• Message Queues

• Shared Memory

Page 28: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 28

Unnamed pipes (pipes)Unnamed pipes (pipes)

• Allow communications between related processes.

• Unidirectional• Used from command line to link commands

– ls -l | more– cat -n myfile.cpp | lpr

• Used in programs to communicate between processes– pipetest.cpp

Page 29: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 29

Pipe CommandsPipe Commands

• popen – FILE * popen (const char* cmd, const char *

type);– type = “r”, “w”

• pclose – int pclose (FILE * stream);

• #include <stdio.h>

Page 30: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 30

Named PipesNamed Pipes

• Permanent objects

• Available to processes that can access the filespace (same system or on a shared file system)

• Processes do not have to be related.

Page 31: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 31

Named Pipes (FIFO)Named Pipes (FIFO)

• int mkfifo(const char *name, mode_t mode);– return is a file descriptor– name is the name of the pipe– mode is the permissions for the pipe (0666 = RDWR

all)

• int open(const char * name, int flags);– flags = O_RDONLY, O_WRONLY, O_RDWR

• ssize_t read(int fd, void *buf, size_t count);

• ssize_t write(int fd, void *buf, size_t count);

Page 32: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 32

Message Queues

• A “linked list of messages”• Message queue has kernel persistence

– Supports asynchronous communications.– Messages are stored in the queue, independent of the

sender (sender can close queue without losing messages).

– Receiver can retrieve messages at a later time.

• Messages have a priority– Higher priority messages are retrieved first (POSIX)– Max priority is 32768

Page 33: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 33

Message Queues

• Message Queue Capacity– (Can be set higher by root)– Max msgs: 10 /queue– Max Msg Size: 8192– Max # of Queues: 256

• Queues are created in their own virtual message queue file system (mqueue)– Can be mounted to view (and manipulate) queues– mkdir /dev/mqueue– mount –t mqueue none /dev/mqueue

Page 34: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 34

Create and/or open a msg queue

• mqd_t mq_open (qName, flags, [mode], [attributes]);– qName: Name of the queue to open / create

• Must be of the form “/qName”.

– flags: How queue will be opened/created.• O_RDONLY | O_WRONLY | O_RDWR , [O_CREAT] )

– mode: File permissions for queue:• S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH

– attributes: Limits for the queue: struct mq_attr• long mq_flags: 0 | O_NONBLOCK (read queue non-blocking?)• long mq_maxmsg: max msgs in queue• long mq_msgsize: max msg size• long mq_curmsgs: How many messages are currently in queue?

Page 35: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 35

Send a message to a queue• mqd_t mq_send (queue_descr, msg, size, prior);

– Queue_descr: Like a file descriptor. Value returned from mq_open.

– Msg: a pointer to a character buffer for the message– Size: (size_t) size of message in bytes– Prior: (unsigned int) priority of message

– Returns 0 on success, -1 on error

Page 36: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 36

Receive a message from a queue

• ssize_t mq_receive (queue_descr, msg, size, prior);– Queue_descr: Like a file descriptor. Value returned from

mq_open.– Msg: a pointer to a character buffer for the message– Size: (size_t) size of buffer in bytes– Prior: (*unsigned int) priority of message read.

– Returns number of bytes read (or -1 on error)

Page 37: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 37

Get attributes of a Queue• mqd_t mq_getattr (queue_descr, *struct

mq_attr);– Queue_descr: Like a file descriptor. Value returned

from mq_open.– *struct mq_attr: Pointer to struct that will return

attributes of the opened queue• long mq_flags: 0 | O_NONBLOCK (read queue non-

blocking?)• long mq_maxmsg: max msgs in queue• long mq_msgsize: max msg size• long mq_curmsgs: How many messages are currently in

queue?

– Returns 0 on success, -1 on error

Page 38: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 38

Removing (unlinking) a queue

• Mqd_t mq_unlink ( qName);– qName: Name of queue

• Queue is removed from the message queue file system. Any messages still in the queue are lost.

• Returns 0 on success, -1 on error

Page 39: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 39

mq_send(Note: All error checking has been removed from the code

to focus on the details of message queue handling)

#include <mqueue.h> (also many other included header files…)#define NAMESIZE 25#define MSGCOUNT 5#define MSGSIZE 512using namespace std;int main (int argc, char **argv) { int lSize, bufSize, stat, i; char qName[NAMESIZE]; char ans[5]; mqd_t mqd; struct mq_attr qAtr; unsigned int prio = 3; char buf[MSGSIZE];

Page 40: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 40

mq_send - 2 strncpy(qName, "/", 2);

strncat (qName, argv[1], lSize+1);

qAtr.mq_maxmsg = MSGCOUNT;

qAtr.mq_msgsize = MSGSIZE;

mqd = mq_open(qName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH, &qAtr);

do {

cout << "What message do you want to send? ";

cin.getline(buf, 80);

bufSize = strlen(buf);

cout << "What is the message priority? ";

cin >> prio;

stat = mq_send(mqd, buf, bufSize, prio);

Page 41: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 41

mq_send - 3 if (stat == 0) cout << "Send was successful" << endl; else exit(0); cout << "Send another message (yes/no)?"; cin >> ans; cin.ignore(); for (i = 0; i < 80; i++)

buf[i] = 0; }while (ans[0] =='y');

mq_close(mqd); return 0;}

Page 42: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 42

mq_recv - 1Note: Most of the error checking code has been removed to focus on

the message queue portions of the code.

#include <mqueue.h> also many other #include files…

#define NAMESIZE 25

#define MSGCOUNT 25

#define MSGSIZE 512

#define BUFSIZE 9000

using namespace std;

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

int lSize, bufSize, stat, msgcount, i, j;

char qName[NAMESIZE];

mqd_t mqd; struct mq_attr qAtr;

unsigned int prio = 3;

char buf[BUFSIZE];

Page 43: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 43

mq_recv - 2 strncpy(qName, "/", 2); strncat (qName, argv[1], lSize+1); mqd = mq_open(qName, O_RDONLY); mq_getattr(mqd, &qAtr); msgcount = qAtr.mq_curmsgs; cout << "There are currently " << msgcount << " messages in queue" << endl; for (i= 0; i < msgcount; i++) { stat = mq_receive(mqd, buf, BUFSIZE, &prio); if (stat >= 0) cout << "msg: " << buf << "; Prio: " << prio << endl; else cout << "Oops! Stat = " << stat << endl; for (j = 0; j < 80; j++)

buf[j] = 0; }//end of for loop mq_close(mqd); mq_unlink(qName); //delete the message queue return 0;}

Page 44: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 44

Sample send Output[rcotter@kc-sce-450p2 msgQ]$ ./mq_send nuQMessage Queue name (/nuQ) is 4 charactersWe opened the queue!What message do you want to send? This is my first test messageWhat is the message priority? 2Send was successfulSend another message (yes/no)?yesWhat message do you want to send? This is my second test messageWhat is the message priority? 4Send was successfulSend another message (yes/no)?yesWhat message do you want to send? This is my third test messageWhat is the message priority? 1Send was successfulSend another message (yes/no)?no[rcotter@kc-sce-450p2 msgQ]$

Page 45: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 45

Sample recv Output

[rcotter@kc-sce-450p2 msgQ]$ ./mq_recv nuQFile name (/nuQ) is 4 charactersWe opened the queue!There are currently 3 messages in queuemsg: This is my second test message; Prio: 4msg: This is my first test message; Prio: 2msg: This is my third test message; Prio: 1[rcotter@kc-sce-450p2 msgQ]$

Page 46: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 46

Shared Memory

• Allows 2 or more processes to share the same main memory space– Memory can be allocated as blocks (pages) of

memory– Memory can be mapped as a file that is available in

memory to multiple processes

Page 47: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 47

Shared Memory

P1

P2

P3

Page 48: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

48

Shared Memory

Page 49: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 49

Shared Memory Usage

• Create a shared memory segment• One or more processes attach to it• Processes read and/or write to the segment.

Note that process sync is critical.• All processes detach from shared memory• One process removes (de-allocates) the

segment

Page 50: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 50

Create a Shared Memory Segment• Requires: <sys/ipc/h>, <sys/shm.h>• int shmget (key_t, int size, int shmflg);

– Key_t:• Shared memory segment number identifier (e.g. 15, 1000). Can be

used to create a new segment or ensure that an existing segment still exists.

• IPC_PRIVATE- special variable that guarantees that a new segment will be created

– Size:• Size of the memory segment. Should be a multiple of th ememory

page size (typically 4096 in Linux).

– Shmflg:• Flags that control behavior of the new segment. • IPC_CREAT, IPC_EXCL, mode bits(9)

– Return (int)• Shared memory ID – used to access or modify the shared memory

Page 51: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 51

Shared Memory Segment Limitsipcs -l

• Maximum segment size– SHMMAX 32768 kbytes

• Minimum segment size– SHMMIN 1 byte

• Total maximum # of segments– SHMMNI 4096

• Total maximum shared memory– SHMALL 8388608 kbytes

Page 52: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 52

Control Shared Memory

• int shmctl (shmid, cmd, struct shmid_ds *buf);– shmid: Shared memory identifier. (Value returned from

shmget())– cmd:

• IPC_STAT – return status information about the shared memory in buf.

• IPC_SET – modify the shared memory based on parameters in buf (can only change UID and mode bits)

• IPC_RMID – Remove (deallocate) the shared memory segment specified in shmid.

• IPC_LOCK – lock the shared memory segment in memory (don’t swap out).

• IPC_UNLOCK –release the lock on shared memory

Page 53: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 53

Attach to a Shared Memory Segment

• void * shmat (shmid, shmaddr, shmflg);– shmid: Shared memory identifier. (Value returned from shmget())

– shmaddr: Address where shared memory should attach to process.• If 0, OS picks a suitable address• If not 0 and SHM_RND flag is set, bind address will be given address,

rounded down to a page boundary• If not 0 and SHM_RND is not set, address must be a page boundary

– shmflg: • SHM_RND – round down the attach address to a page boundary• SHM_RDONLY – open for read only. Process must have read access to the

segment

– Return value: Address at which the shared memory is mapped.

Page 54: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 54

Detach from Shared Memory Segment

• int shmdt (shmaddr);– shmaddr – address at which shared memory is

attached– return 0 for success, -1 for fail

Page 55: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

55

Shared Memory Example#include <iostream>, etc…#define SHM_SIZE 2048#define ARRAYSIZE 50#define LOOPCOUNT 1000000#define PCOUNT 3

using namespace std;

int main( ) { int shmid, i, j, k, sum, *shm, *myNum;

int pid, procNum, n1, n2; int myNumbers[ARRAYSIZE]; int s[3]; //seeds for rand();

char sem1[] = “/semBlock”;sem_t *Scount;for (i = 0; i < ARRAYSIZE; i++) //Fill array with 0-49. Sum = 1225 myNumbers[i] = i;

Page 56: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

56

Shared Memory Exampleif ((shmid=shmget(IPC_PRIVATE,SHM_SIZE,IPC_CREAT|0660))< 0) {

perror("shmget fail"); return 1; } if ((shm = (int *)shmat(shmid, 0, 0)) == (int *) -1) { perror("shmat : parent"); return 2; } cout << "Shared memory is at: " << hex << shm << dec << endl; myNum = shm; // myNum now references shared mem //Now we need to copy our array of numbers into shared memory memcpy (myNum, &myNumbers, sizeof(myNumbers)); sum = 0; for (i = 0; i < ARRAYSIZE; i++) {

cout << myNum[i] << " , ";sum += myNum[i];

} cout << "\nThe sum of all values is " << sum << endl; cout << "In parent before fork, memory is: " << shm << endl; Scount = sem_open(sem1, O_CREAT, 0666, 1); sem_close (Scount);

Page 57: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

57

Shared Memory Examplefor (i = 0; i < PCOUNT; i++) {

if ((pid = fork()) < 0) //fork failed { cout << "Fork failed!!" << endl;return 2;

} else if (pid == 0) //We're in the child {

srand(s[i]); // seed the random number generatorprocNum = i;Scount = sem_open(sem1, 0);cout << "In child " << procNum << " memory is: " << shm << endl;for (j = 0; j < LOOPCOUNT; j++) {

n1 = (rand() % 50);n2 = (rand() %50);sem_wait (Scount);myNum[n1]+= 1;myNum[n2] -= 1;sem_post (Scount);

}//end of for ...sem_close(Scount);return 0; //child is done.

} //end of if pid == 0 else //We're in the parent {

cout << "We just created child " << i << " with pid " << pid << endl;}//end of for ---PCOUNT

Page 58: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

58

Shared Memory Example

//The parent now needs to wait for the children (at least 1) to finishwait(0);cout << "In parent after fork, memory is : " << shm << endl;sum = 0;for (i = 0; i < ARRAYSIZE; i++) {

cout << myNum[i] << " , ";sum += myNum[i];

}cout << "\nThe sum of the array is now " << sum << endl;cout << "\nParent removing shared memory" << endl;sem_unlink(sem1);shmdt(shm);shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0);return 0;

}

Page 59: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

59

Shared Memory Example – W/ Sync

rcotter@kc-sce-450p2 shmem]$ ./sharedmem_sShared memory is at: 0xb78ed0000 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 ,The sum of all values is 1225In parent before fork, memory is: 0xb78ed000We just created child 0 with pid 18745In child 0 memory is: 0xb78ed000We just created child 1 with pid 18746The sum for child 0 is 1225In child 2 memory is: 0xb78ed000The sum for child 2 is 1225We just created child 2 with pid 18747In child 1 memory is: 0xb78ed000The sum for child 1 is 1225:The sum for child 2 is 1225Child 0 just did 1000000 loopsChild 18745 just terminatedThe sum for child 1 is 1225:Child 1 just did 1000000 loopsChild 18746 just terminatedThe sum for child 2 is 1225:Child 2 just did 1000000 loopsChild 18747 just terminatedIn parent after fork, memory is : 0xb78ed000167 , 425 , 83 , 320 , 162 , -387 , -120 , -236 , 712 , 548 , 136 , -391 , -82 , 561 , -362 , -115 , 555 , 7 , -169 , -492 , -459 , 113 , -58 , 19 , 130 , -581 , 266 , 36 , 524 , -272 , -393 , -119 , -65 , 24 , 495 , 367 , -315 , -225 , -146 , 515 , -173 , 321 , -91 , -60 , 69 , -111 , 6 , 468 , -56 , -326 ,The sum of the array is now 1225

Parent removing shared memory[rcotter@kc-sce-450p2 shmem]$

Page 60: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

60

Shared Memory Example – W/O Sync

[rcotter@kc-sce-450p2 shmem]$ ./sharedmemShared memory is at: 0xb77cb0000 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 ,The sum of all values is 1225In parent before fork, memory is: 0xb77cb000We just created child 0 with pid 18681We just created child 1 with pid 18682We just created child 2 with pid 18683In child 2 memory is: 0xb77cb000The sum for child 2 is 1225In child 0 memory is: 0xb77cb000The sum for child 0 is 1226In child 1 memory is: 0xb77cb000The sum for child 1 is 1222The sum for child 0 is 1221:Child 18681 just terminated.The sum for child 2 is 343The sum for child 1 is 343:Child 18683 just terminated.The sum for child 1 is 290:Child 18682 just terminated.In parent after fork, memory is : 0xb77cb000-204 , -443 , -85 , -339 , -178 , 390 , 101 , 232 , -717 , -548 , -116 , 384 , 102 , -533 , 365 , 123 , -537 , 52 , 217 , 497 , 485 , -101 , 100 , -4 , -99 , 619 , -216 , 6 , -500 , 316 , 432 , 152 , 98 , 29 , -433 , -333 , 368 , 289 , 187 , -461 , 232 , -257 , 152 , 130 , 4 , 175 , 30 , -386 , 121 , 392 ,The sum of the array is now 290Each process ran through 1000000 iterationsParent removing shared memory[rcotter@kc-sce-450p2 shmem]$

Page 61: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 61cs431-cottercs431-cotter

SummarySummary• Several different sync mechanisms available in

Linux– Signal– Wait – Mutex– Semaphore

• Several different IPC mechanisms– Pipes– Message queues– Shared Memory

• Linux specifications consistent with POSIX

Page 62: Cs431-cotter1 Linux Process Synchronization Tanenbaum 10.3, 2.3 Linux man pthread_mutex_init, etc. The Linux Programming Interface - Kerrisk Interprocess

cs431-cotter 62cs431-cottercs431-cotter

QuestionsQuestions• What is a signal handler table? Where is it located? How is it used

by a process to handle signals sent to the process? • How do you set up a program (process) to provide customized

handling of a signal? (What code is needed to replace the default signal handler with our own signal handling routine?

• What function would a parent process use to capture the exit code of a terminated child process? If the parent process creates multiple child processes, how could it wait for one specific child process to terminate?

• If two processes want to pass information using an named pipe, what must the relationship be between those processes (no relation required, parent and child, children of the same parent, processes in the same system, etc.)

• What functions (system calls) would be needed to create and initialize a semaphore in Linux? What functions are needed to actually use the semaphore in your program?