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

Slides:



Advertisements
Similar presentations
Inter-Process Communication: Message Passing Tore Larsen Slides by T. Plagemann, Pål Halvorsen, Kai Li, and Andrew S. Tanenbaum.
Advertisements

Operating Systems Lecture 7.
Unix IPC and Synchronization. Pipes and FIFOs Pipe: a circular buffer of fixed size written by one process and read by another int pipe(int fildes[2])
Shared Memory  Creating a Shared Memory Segment Allocated in byte amounts  Shared Memory Operations Create Attach Detach  Shared Memory Control Remove.
XSI IPC Message Queues Semaphores Shared Memory. XSI IPC Each XSI IPC structure has two ways to identify it An internal (within the Kernel) non negative.
Week Fourteen Agenda Announcements Final Exam True/False -100 questions (1 point per question) Multiple Choice - 40 questions (2 points per question)
2.3 InterProcess Communication (IPC) Part A. IPC methods 1. Signals 2. Mutex (MUTual EXclusion) 3. Semaphores 4. Shared memory 5. Memory mapped files.
System V IPC (InterProcess Communication) Messages Queue, Shared Memory, and Semaphores.
1 Select and poll and Signals CS 241 April 6, 2012 University of Illinois.
Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.
Page 1 Task Control: Signals and Alarms Chapter 7 and 8 B. Ramamurthy.
Exec function Exec function: - replaces the current process (its code, data, stack & heap segments) with a new program - the new program starts executing.
CS Lecture 17 Outline Named pipes Signals Lecture 17
Inter Process Communication:  It is an essential aspect of process management. By allowing processes to communicate with each other: 1.We can synchronize.
UNIX IPC CSE 121 Spring 2003 Keith Marzullo. CSE 121 Spring 2003Review of Concurrency2 Creating a UNIX process A process is created by making an exact.
Posix Message Queues Courtesy of W. Richard Stevens Unix Network Programming Volume 2: Interprocess Communication.
Project 1. Process ID (pid) Synopsis #include pid_t getpid(void) – returns the pid of the currently running process. pid_t getppid(void) – returns the.
CS Lecture 16 Outline Inter-process Communication (IPC) – Pipes – Signals Lecture 161CS Operating Systems 1.
Linux Operating System
NCHU System & Network Lab Lab 10 Message Queue and Shared Memory.
Processes in Unix, Linux, and Windows CS-502 Fall Processes in Unix, Linux, and Windows CS502 Operating Systems (Slides include materials from Operating.
Inter Process Communication. Introduction Traditionally describe mechanism for message passing between different processes that are running on some operating.
Inter-Process Communication: Message Passing
Inter-Process Communication Mechanisms CSE331 Operating Systems Design.
1Reference “Introduction To Unix Signals Programming” in the reference material section Man page – sigprocmask, alarm “Understanding the Linux Kernel”
Thread Synchronization with Semaphores
S -1 Shared Memory. S -2 Motivation Shared memory allows two or more processes to share a given region of memory -- this is the fastest form of IPC because.
System V IPC Provides three mechanisms for InterProcess Communication (IPC) : Messages : exchange messages with any process or server. Semaphores : allow.
Module 2 Programming with Processes. Processes Process -- a program in execution –May share code segments –Typically do not share data, stack, heap OS.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 8: Opening Files and Starting Processes.
The kernel considers each program running on your system to be a process A process lives as it executes, with a lifetime that may be short or long A process.
Florida State UniversityCOP5570 – Advanced Unix Programming Today’s topics System V Interprocess communication (IPC) mechanisms –Message Queues –Semaphores.
1 Shared Memory. 2  Introduction  Creating a Shared Memory Segment  Shared Memory Control  Shared Memory Operations  Using a File as Shared Memory.
Process Control Process identifiers Process creation fork and vfork wait and waitpid Race conditions exec functions system function.
Agenda  Working with Processes: Purpose Running Programs within same process (execl, execlp, execle, execv, execvp, execve) “Spawning” other process (fork,
System calls for Process management
Semaphores Creating and Accessing Semaphore Sets Semaphore Operations
Scis.regis.edu ● CS 468: Advanced UNIX Class 5 Dr. Jesús Borrego Regis University 1.
IPC Programming. Process Model Processes can be organized into a parent-child hierarchy. Consider the following example code: /* */
Week Fourteen Agenda Announcements Final Exam True/False -100 questions (1 point per question) Multiple Choice - 40 questions (2 points per question)
UNIX Socket Programming CS 6378 Project Reference Book: Unix Network programming: Networking APIs: Sockets and XTI (2nd edition), Prentice Hall >> Threads.
Concurrent Processes Processes can concurrently run same program. Processes can concurrently run same program. Processes can start other processes. Processes.
Operating Systems Process Creation
Signals and Signal Processing CIS 370 Lab 7 Umass Dartmouth.
1 Signals (continued) CS 241 April 9, 2012 University of Illinois.
2.3 interprocess communcation (IPC) (especially via shared memory & controlling access to it)
File descriptor table File descriptor (integer)File name 0stdin 1stdout 2stderr Use open(), read(), write() system calls to access files Think what happens.
UNIX Signals * POSIX-Defined Signals * Signaling Processes * Signal Mask * sigaction * kill and sigaction * alarm * Interval Timers * POSIX.1b Timers *
Interprocess Communication Mechanisms. IPC Signals Pipes System V IPC.
Interprocess Communication Anonymous Pipes Named Pipes (FIFOs) popen() / pclose()
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Unix System Calls and Posix Threads.
CSCI 330 UNIX and Network Programming Unit VII: I/O Management I.
Today’s topic Environment variables Signal. The list of environment variables –try ‘env’ –Environment variables can be defined in shell setenv DISPLAY.
Named Pipes. Kinds of IPC u Mutexes/Conditional Variables/Semaphores u Pipes u Named pipes u Signals u Shared memory u Messages u Sockets.
Signals & Message queue Inter process mechanism in Linux system 3/24/
ACCESS CONTROL. Components of a Process  Address space  Set of data structures within the kernel - process’s address space map - current status - execution.
Shared Memory Dr. Yingwu Zhu. Overview System V shared memory Let multiple processes attach a segment of physical memory to their virtual address spaces,
S -1 Processes. S -2 wait and waitpid (11.2) Recall from a previous slide: pid_t wait( int *status ) wait() can: (a) block; (b) return with status; (c)
System calls for Process management Process creation, termination, waiting.
UNIX signals.
Task Control: Signals and Alarms Chapter 7 and 8
Threads and Cooperation
Shared Memory Dr. Yingwu Zhu.
Interprocess Communication (IPC)
OPERATING SYSTEMS DESIGN AND IMPLEMENTATION Third Edition ANDREW S
CSC Advanced Unix Programming, Fall 2015
Inter-Process Communication ENCE 360
CSE 451: Operating Systems Spring 2006 Module 4 Processes
Signals.
Shared Memory Dr. Yingwu Zhu Feb, 2007.
Presentation transcript:

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

cs431-cotter2 Overview Linux IPC Signal Alarm Wait Semaphore (named and unnamed) Mutex Pipe ( named and unnamed) Messages Shared Memory

cs431-cotter3 Linux 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.

cs431-cotter4 Figure The signals required by POSIX. Signals in Linux Tanenbaum, Modern Operating Systems 3 e, (c) 2008 Prentice-Hall, Inc. All rights reserved

cs431-cotter5 Signals 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE 9) SIGKILL10) SIGBUS11) SIGSEGV12) SIGSYS 13) SIGPIPE14) SIGALRM15) SIGTERM16) SIGURG 17) SIGSTOP18) SIGTSTP19) SIGCONT20) SIGCHLD 21) SIGTTIN22) SIGTTOU23) SIGIO24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM27) SIGPROF28) SIGWINCH 29) SIGINFO30) SIGUSR131) SIGUSR2 Current versions of Linux support 64 signals (real time signals added). See: man 2 signal, man 2 sigaction man 7 signal

cs431-cotter6 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. };

cs431-cotter7 Alarm 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);

cs431-cotter8 Sig_alarm.cpp #include using namespace std; #define MAXLINE 128 static 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;

cs431-cotter9 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; }

cs431-cotter10 sig_alarm.cpp Output cs431]$ g++ -o sigtest sig_alarm3.cpp cs431]$./sigtest This is a test cs431]$./sigtest This is another ### We got the alarm signal!! ### test This is another test cs431]$

cs431-cotter11 wait( ) #include 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.

cs431-cotter12 waittest1.c #include int main() { pid_tpid; intstatus; printf("Forking child process...\n"); if ((pid = fork()) < 0) { printf("fork failed!\n"); exit(1); }

cs431-cotter13 waittest1.c else 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); }

cs431-cotter14 waittest.c output gcc -o waittest waittest1.c Forking child process... Child process is shutting down Normal Termination. Exit value 7 Parent shutting down...

cs431-cotter15 Semaphores POSIX version of semaphores –#include –classic semaphore implementation System V version of semaphores –#include –Enhanced version of semaphores to include sets

cs431-cotter16 POSIX (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)

cs431-cotter17 Example Semaphore fragment sem_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.... }

18cs431-cotter18 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

19 Named Semaphore example producer - 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 semaphores char sem2[] = "/semFull"; char sem3[] = "/semFlag"; int buf[BUFSIZE]; /* shared buffer */ int mycount; static void sig_alarm(int signo);

20 Named Semaphore example int 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;

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

22 Named Semaphore example void *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 now usleep(rand () %997); } return &buf[0]; }

23 Named Semaphore example void *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; }

cs431-cotter24 Figure 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

cs431-cotter25 Figure 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

cs431-cotter26 Figure 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

27 Linux Interprocess Communications Unnamed Pipes Named Pipes Message Queues Shared Memory

cs431-cotter28 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

cs431-cotter29 Pipe Commands popen –FILE * popen (const char* cmd, const char * type); –type = “r”, “w” pclose –int pclose (FILE * stream); #include

cs431-cotter30 Named 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.

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

cs431-cotter32 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

cs431-cotter33 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

cs431-cotter34 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?

cs431-cotter35 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

cs431-cotter36 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)

cs431-cotter37 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

cs431-cotter38 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

cs431-cotter39 mq_send (Note: All error checking has been removed from the code to focus on the details of message queue handling) #include (also many other included header files…) #define NAMESIZE 25 #define MSGCOUNT 5 #define MSGSIZE 512 using 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];

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

cs431-cotter41 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; }

cs431-cotter42 mq_recv - 1 Note: Most of the error checking code has been removed to focus on the message queue portions of the code. #include 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];

cs431-cotter43 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; }

cs431-cotter44 Sample send Output msgQ]$./mq_send nuQ Message Queue name (/nuQ) is 4 characters We opened the queue! What message do you want to send? This is my first test message What is the message priority? 2 Send was successful Send another message (yes/no)?yes What message do you want to send? This is my second test message What is the message priority? 4 Send was successful Send another message (yes/no)?yes What message do you want to send? This is my third test message What is the message priority? 1 Send was successful Send another message (yes/no)?no msgQ]$

cs431-cotter45 Sample recv Output msgQ]$./mq_recv nuQ File name (/nuQ) is 4 characters We opened the queue! There are currently 3 messages in queue msg: This is my second test message; Prio: 4 msg: This is my first test message; Prio: 2 msg: This is my third test message; Prio: 1 msgQ]$

cs431-cotter46 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

cs431-cotter47 Shared Memory P1 P2 P3

48 Shared Memory

cs431-cotter49 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

cs431-cotter50 Create a Shared Memory Segment Requires:, 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

cs431-cotter51 Shared Memory Segment Limits ipcs -l Maximum segment size –SHMMAX32768 kbytes Minimum segment size –SHMMIN1 byte Total maximum # of segments –SHMMNI4096 Total maximum shared memory –SHMALL kbytes

cs431-cotter52 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

cs431-cotter53 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.

cs431-cotter54 Detach from Shared Memory Segment int shmdt (shmaddr); –shmaddr – address at which shared memory is attached –return 0 for success, -1 for fail

55 Shared Memory Example #include, etc… #define SHM_SIZE 2048 #define ARRAYSIZE50 #define LOOPCOUNT #define PCOUNT3 using namespace std; int main( ) { int shmid, i, j, k, sum, *shm, *myNum; int pid, procNum, n1, n2; intmyNumbers[ARRAYSIZE]; int s[3]; //seeds for rand(); char sem1[] = “/semBlock”; sem_t*Scount; for (i = 0; i < ARRAYSIZE; i++) //Fill array with Sum = 1225 myNumbers[i] = i;

56 Shared Memory Example if ((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);

57 Shared Memory Example for (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 generator procNum = 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

58 Shared Memory Example //The parent now needs to wait for the children (at least 1) to finish wait(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; }

59 Shared Memory Example – W/ Sync shmem]$./sharedmem_s Shared memory is at: 0xb78ed000 0, 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 1225 In parent before fork, memory is: 0xb78ed000 We just created child 0 with pid In child 0 memory is: 0xb78ed000 We just created child 1 with pid The sum for child 0 is 1225 In child 2 memory is: 0xb78ed000 The sum for child 2 is 1225 We just created child 2 with pid In child 1 memory is: 0xb78ed000 The sum for child 1 is 1225 : The sum for child 2 is 1225 Child 0 just did loops Child just terminated The sum for child 1 is 1225 : Child 1 just did loops Child just terminated The sum for child 2 is 1225 : Child 2 just did loops Child just terminated In parent after fork, memory is : 0xb78ed , 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 shmem]$

60 Shared Memory Example – W/O Sync shmem]$./sharedmem Shared memory is at: 0xb77cb000 0, 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 1225 In parent before fork, memory is: 0xb77cb000 We just created child 0 with pid We just created child 1 with pid We just created child 2 with pid In child 2 memory is: 0xb77cb000 The sum for child 2 is 1225 In child 0 memory is: 0xb77cb000 The sum for child 0 is 1226 In child 1 memory is: 0xb77cb000 The sum for child 1 is 1222 The sum for child 0 is 1221 : Child just terminated. The sum for child 2 is 343 The sum for child 1 is 343 : Child just terminated. The sum for child 1 is 290 : Child just terminated. In parent after fork, memory is : 0xb77cb , -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 290 Each process ran through iterations Parent removing shared memory shmem]$

cs431-cotter61cs431-cotter Summary 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

cs431-cotter62cs431-cotter Questions 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?