Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
Inter-process communication
Trifon Ruskov [email protected]
Technical University of Varna - Bulgaria
Trifon Ruskov Technical University - Varna 2
Process Communication and Synchronization
The UNIX IPC (Inter-process communications) facilities provide methods for multiple processes to communicate with one another:
SignalsHalf-duplex UNIX pipesNamed pipesMessage queuesShared memory segmentsSemaphore sets
Trifon Ruskov Technical University - Varna 3
Signals in Unix
Signals are software-generated interrupts that are sent to a process when an event happens.
Signals can be posted to a process when the system detects a software event.
Signals can also come directly from the kernel when a hardware event is encountered.
Each signal has a default action:The signal is discardedThe process terminate
Each signal falls into one of five classes:Hardware conditionSoftware conditionInput/output notificationProcess controlResource control
Trifon Ruskov Technical University - Varna 4
Signals in Unix (cont.)
Signal definitions are in <signal.h>
#define SIGHUP 1 /* hang up */#define SIGINT 2 /* interrupt */#define SIGQIUT 3 /* quit */#define SIGILL 4 /* illegal instruction */#define SIGTRAP 5 /* hardware interrupt */#define SIGKILL 9 /* hard kill */#define SIGALRM 14 /* alarm clock */
etc.
Trifon Ruskov Technical University - Varna 5
Sending Signals
A system call that sens a signal (signal) to a process (pid)
int kill (int pid, int signal)
returns: 0 – successful call-1 – otherwise (errorno is set)
From the Linux shell:
kill –9 37
Trifon Ruskov Technical University - Varna 6
Signal Handling
An application program can specify a function, called a signal handler, to be invoked when a specific signal is received. When a signal handler is invoked on receipt of a signal, it is said to catch the signal.
A process can deal with a signal in one of the following ways:The process can let the default action happen.The process can block the signal (some signals cannot be ignored).The process can catch the signal with a handler.
Receiving signals is straightforward with the function:
int (* signal (int sig, void (*func)())) ()
The function signal() will call the function pointed to by func if the process receives a signal sig.
Trifon Ruskov Technical University - Varna 7
Signal Handling (cont.)
func can have three values:SIG_DFL – a pointer to the system default function SIG_DFL ( )SIG_IGN – a pointer to the system ignore function SIG_IGN ( )function – a user specified function
Examples:1. To ignore a Ctrl/C command from command line
signal(SIGINT, SIG_IGN);
2. To reset system to default actionsignal(SIGINT, SIG_DFL);
Trifon Ruskov Technical University - Varna 8
Signal Handling (cont.)
3. To trap a Ctrl/C but not quit on this signal
#include <stdio.h>#include <signal.h>
void sigproc(void);void quitproc(void);
int main(){ signal(SIGINT, sigproc);signal(SIGQUIT, quitproc);for(;;); // infinite loop
}
void sigproc(){ signal(SIGINT, sigproc); printf(”CTRL/C pressed\n”);
}
void quitproc(){exit(0);
}
Trifon Ruskov Technical University - Varna 9
Signal Handling (cont.)
4. To delete a temporary file after abnormal termination
#include <signal.h>
void cleanup(void);
int main () {signal(SIGINT, cleanup);...creat(tempfile, 0);...unlink(tempfile);exit(0);
}
void cleanup() {unlink(tempfile);exit(1);
}
Trifon Ruskov Technical University - Varna 10
Signal Handling (cont.)
Note:
Signals are reset to default when accepted by signal handler. Why?
System call pause:
pause();
Stop the process until some signal is received.
Trifon Ruskov Technical University - Varna 11
Pipes in Unix
Pipes provide one-way (half-duplex) communications between related processes.Pipes are implemented based on the kernel I/O buffers.A pipe is a tool for connecting the standard output of one process to the standard input of another process, typically used in UNIX shell pipelines.
Example:
Counting of files in current directory: ls > tmpfile && wc –w tmpfile && rm tmpfile
The same example with a shell pipeline:ls | wc –w
The pipeline reduces execution time by:Parallel execution of the commandsAvoiding disk operations for temporary saving of intermediate dataNo temporary files to be deleted
Trifon Ruskov Technical University - Varna 12
Pipes in Unix (cont.)
Pipes are accessed in a similar way as ordinary files:They have assigned inodes. Reading and writing are through file descriptors.
Differences between pipes and files:The pipe inode resides in the kernel, not in the physical file system.A pipe can exist only during the existence of its creator process.A pipe has limited size.
P1
kernel I/O buffers P2
fd0fd1
stdinstdout
Trifon Ruskov Technical University - Varna 13
Creating PipesSystem call that creates a pipe:
int pipe(int fd[2]);
Parameters:fd[] – array of file descriptors
returns:0 – successful call-1 – otherwise (errorno is set)
This call opens two file descriptors:fd[0] – file descriptor for readingfd[1] – file descriptor for writing
Example:Redirecting the standard output to a pipe
int fd[2];
pipe(fd); // Create a pipeclose(1); // Close stdoutdup2(1, fd[1]); // Duplicate stdout to the fd[1]close(fd[1]); // Close fd[1]
Trifon Ruskov Technical University - Varna 14
Using Pipes Process, created a pipe, can use it to communicate with a child process.A child process inherits any open file descriptors from the parent, including pipe descriptors.Communicating processes must close unused file descriptor of the pipe.
Example:
int main() {int fd[2], pid;
pipe(fd);if (pid=fork()) == -1 ) {perror(“fork”);exit(1);
}if (pid == 0)close(fd[0]); // Child process closes input side of pipe
else close(fd[1]); // Parent process closes output side of pipe
}
Trifon Ruskov Technical University - Varna 15
Example: Implementation of ls | wc –w#include <stdio.h>#include <unistd.h>#include <sys/types.h>int main() {int fd[2], dead, status;if (fork()) wait(&status);else {
pipe(fd); if (fork()) {close(1);dup2(1, fd[1]);close(fd[1]);close(fd[0]);execl(“/bin/ls”, “ls”, 0);
} else {close(0);dup2(0, fd[0]);close(fd[0);close(fd[1]);execl(“/usr/bin/wc”, “wc”, “-w”, 0);
}}
}
ls
pipe
wc -w
stdinstdout
Trifon Ruskov Technical University - Varna 16
Example: Read/Write through a Pipe#include <stdio.h>#include <unistd.h>#include <sys/types.h>
int main(void){int fd[2], nbytes, status;pid_t childpid;char string[] = "Hello!\n";char readbuffer[20];
pipe(fd);if(!fork()){
close(fd[0]); // Child process closes input side of pipe //Send "string" through the pipewrite(fd[1], string, strlen(string));exit(0);
} else {close(fd[1]); // Parent process closes output side of pipe // Read in a string from the pipenbytes = read(fd[0], readbuffer, sizeof(readbuffer));printf("Received string: %s", readbuffer);wait(&status);
}return(0);
}
parent
pipe
child
writereadfd[1]fd[0]
Trifon Ruskov Technical University - Varna 17
Inter-process communication with pipes and signals
main program
pipe
slave programs
P1
P2
Pn
P0
SIGFPE
ttyn
tty2
tty1
tty0
SIGTERM
Trifon Ruskov Technical University - Varna 18
Inter-process communication with pipes and signals (cont.)
Slave program:#include <signal.h>#include <sys/types.h>#include <sys/tty.h>
int main(int argc, char *argv[]) {int n;char bufer[TTYHOG];
for (;;) {n = read(0, buffer, TTYHOG];if (n == 0) { // Reached EOF
kill(atoi(argv[1]), SIGFPE);close(1);exit(NULL);
}kill(atoi(argv[1])), SIGTERM);write(1, buffer, n);
}}
Trifon Ruskov Technical University - Varna 19
Inter-process communication with pipes and signals (cont.)
Main program:#include <signal.h>#include <stdio.h>#include <sys/types.h>#include <sys/tty.h>
int fd[2];char pids[TTYHOG];int slave_count;
void service() { // SIGTERM processingint n;char buffer[TTYHOG];
signal(SIGTERM, service);n = read(fd[0], buffer, TTYHOG];write(1, buffer, n);
}void slavedrop() { // SIGFPE processingsignal(SIGFPE, slavedrop);If (--slave_count = 0)
exit(NULL);}
Trifon Ruskov Technical University - Varna 20
Inter-process communication with pipes and signals (cont.)void slave(char *tty) { // Slave program initializationif (fork() == 0) {
int tfd;
// stdio redirection to a terminalclose(0);tfd = open(tty, 0);if (tfd != 0) {
fprintf(stderr, “bad tty %s\n”, tty);exit(1);
}// stdout redirection to a pipeclose(1);dup(fd[1]);close(fd[1]);close(fd[0]);// Execute the slave programexecl(“./slave”, “slave”, pids, 0);fprintf(stderr, “Can’t exec slave on %s\n”, tty);exit(1);
}}
Trifon Ruskov Technical University - Varna 21
Inter-process communication with pipes and signals (cont.)
// Main program. Started as <program_name> /dev/tty1 /dev/tty2
int main(int argc, char *argv[]) {int i;
signal(SIGTERM, service);signal(SIGFPE, slavedrop);sprintf(pids, “%06d”, getpid());pipe(fd);slave_count = argc – 1;for (i=1; i<argc; i++)
slave(argv[i]);close(fd[1]);for (;;)
pause();}
Trifon Ruskov Technical University - Varna 22
Named pipes
Named pipes are used for inter-process communications.
Features:Exist as special files in the physical file systemAny unrelated processes can access a named pipe and share data through itAccess to named pipes is regulated by the usual file permissionsPipe data is accessed in a FIFO styleOnce created, a named pipe remains in the file system until explicitly deleted
Creation:By UNIX shell commands. Example:mknod <filename> pmkfifo a=rw <filename>
By systems calls. Example:mknod(char *pathname, mode_t mode, dev_t dev);mknod(“/tmp/myfifo”, S_IFIFO | 0660, 0);
Trifon Ruskov Technical University - Varna 23
Named pipes (cont.)
Same I/O operations style on named pipes and regular files – open(), read() and write() calls.
Implementation of I/O operations:By system calls.By library functions.
Semantics of open() call:Blocking. The process that opens the named pipe for reading, sleeps until another process opens it for writing, and v.v.Non-blocking. Flag O_NONBLOCK, used in open() call disables default blocking.
Pipes have size limitations.
Trifon Ruskov Technical University - Varna 24
Named pipes. ExampleClient-server communication through a pipeServer#include <fcntl.h>...#define PIPE "fifo"
int main(){int fd;char readbuf[20];
mknod(PIPE, S_IFIFO | 0660, 0); // create pipefd = open(PIPE, O_RDONLY, 0); // open pipefor (;;) {
if (read(fd, &readbuf, sizeof(readbuf)) < 0){ //read from pipeperror("Error reading pipe");exit(1);
} printf("Received string: %s\n", readbuf); // process data
}exit(0);
}
server
pipe
client
Trifon Ruskov Technical University - Varna 25
Named pipes. Example (cont.)
Client#include <stdio.h>...
#define PIPE “fifo”
int main(){int fd;char writebuf[20] = “Hello”; // open pipe
fd = open(PIPE, O_WRONLY, 0);// write to pipewrite(fd, writebuf, sizeof(writebuf));
exit(0);}
Trifon Ruskov Technical University - Varna 26
Inter-Process Communication (IPC)
Unix System V IPC facilities provide a method for multiple processes to communicate with one another. There are several methods of IPC available to UNIX programmers:
MessagesShared memorySemaphores
Each method is based on a specific object. The objects of various methods have some common features. They:
are described in a tablehave unique kernel identifiershave unique user keyshave individual access permissionshave status information collectedare dynamically created and deleted
Trifon Ruskov Technical University - Varna 27
Inter-Process Communication (cont.)
To share an object, a process must:be able to identify it (know its key)have appropriate privilegesgain access by a “get” system call
The particular “get” system call for each method is used for:Creating an object (if it doesn’t exist)Checking process permissionsAssociating an unique ID to the key
Unix shell commands for IPC:ipcs – shows the status of all IPC objectsipcrm msg/shm/sem <object_ID> - deletes a particular object
Trifon Ruskov Technical University - Varna 28
IPC Messages
Features of the IPC message method:Two or more processes can exchange information through a system message queue.The sending process places a message into the queue.The receiving process reads a message from the queue.Messages have a type, used by the process to select appropriate message.Message have a fixed length.Processes must share a common key to gain access to the message queue.
Trifon Ruskov Technical University - Varna 29
IPC Messages Mechanism
Internal data structures, maintained by the kernel:
msgID
message data
message data
message data
data areaqueue headers message headers
type size
type size
type size
Trifon Ruskov Technical University - Varna 30
IPC Messages Mechanism (cont.)
Message queue header contains:The queue keyThe queue permissionsTimes of the last send and receive operations on queue and pid of their initiatorsMessage data and current queue statePointers to queues of processes, blocked on send and receive operations
Message structureType (positive number), used for selecting a message from the queueData with an application-dependent format
Trifon Ruskov Technical University - Varna 31
Getting Access to a Message Queue
int msgget(key_t key, int flag);
Parameters:key – an user defined value, associated with a message queueflag - control flags and settings for the queue permissions
returns:msgID – message queue identifier on success-1 – otherwise (errno is set)
This system call compares the given key to values that exist within the kernel for other message queues. At that point, the open or access operation is dependent upon the contents of the flag argument:
IPC_CREAT - create the queue if it doesn’t already exist in the kernel.IPC_CREAT | IPC_EXCL – function fails if required queue already exists.
Trifon Ruskov Technical University - Varna 32
Sending Messages
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
Parameters:msgid – a message queue identifier.msgp – a pointer to a message buffer in the process address space.mgsz - size of the message text in bytes.msgflg – set to 0 or IPC_NOWAIT.
returns:0 – on success-1 – otherwise (errno is set)
The function attempts to put the message, pointed by the msgp, into the existing queue with identifier msgid. The message must be previously constructed with type and text (data).
Trifon Ruskov Technical University - Varna 33
Sending Messages (cont.)
Example of message structure:struct mymsg {long mtype; // message typechar mtext[MSGSZ]; // message data with MSGSZ length
}
The following action of msgsnd are possible:The message is successfully put into the message queue. The calling process is blocked – not enough free space in the queue.Error code is returned.
Send operations may be blocking or non-blocking:Blocking is the default action in case of full queue.Blocking can be prevented if IPC_NOWAIT is set as msgflg argument of the msgsnd(). The calling process will return immediately with an error code.
Trifon Ruskov Technical University - Varna 34
Receiving Messages
int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
Parameters:msgid – a message queue identifier.msgp – a pointer to a message buffer in the process address space.mgsz - size of the message text in bytes.msgtyp - the received message type as specified by the sending process. msgflg – set to 0 or IPC_NOWAIT.
returns:Number of bytes, copied into *msgp – on success-1 – otherwise (errno is set)
The function takes a message from the queue with identifier msgid and writes it in process address space, pointed to by msgp.
Trifon Ruskov Technical University - Varna 35
Receiving Messages (cont.)The appropriate message is selected according the value of msgtyp:
msgtyp = 0 – select the first message in the message queue.msgtyp > 0 – select the first message with type = msgtyp.msgtyp < 0 – select the first message with type <= |msgtyp|.
The following actions of msgrcv are possible:The needed message is selected and extracted from the queue. Onewaiting process is waken up and allowed to perform send operation.The calling process is blocked – no message in the queue.Error code is retuned.
Receive operations may be blocking or non-blocking:Blocking is the default action in case of empty queue or requested message is not found.Blocking can be prevented if IPC_NOWAIT is set as msgflg argument of the msgrcv(). The calling process will return immediately with an error code.
If the size of the physical message data is greater than msgsz, and flagMSG_ NOERROR is asserted, then the message is truncated, and only msgszbytes are returned.
Trifon Ruskov Technical University - Varna 36
Controlling Message Queues
Direct manipulation of internal kernel message structures can be done by:int msgctl(int msqid, int cmd, struct msqid_ds *buf);
Parameters:msgid – a message queue identifier.cmd – one of:
IPC_STAT – gets information about the status of the queue and stores it in the address pointed to by buf.IPC_SET – set permissions and other information for the queue.IPC_RMID – remove the message queue msgid.
buf – pointer to data buffer.returns:
0 – on success-1 – otherwise (errno is set)
Trifon Ruskov Technical University - Varna 37
IPC Messages. Example// Message-receiver process#include <sys/ipc.h>#include <sys/msg.h>...
#define KEY 75#define MSGSIZE 70#define MSGTYPE 5typedef struct msgs {
long mtype;char mtext[MSGSIZE];
} msg_str;
int main (){int msgid;msg_str msg;
msgid = msgget(KEY, IPC_CREAT | 0660); // Create message queue and get its ID
...if (msgrcv(msgid, (struct msgbuf *)&msg, MSGSIZE, MSGTYPE, 0) < 0){
perror("msgrcv"); exit(1); }// msg processing...
}
P1 P2
message queue
Trifon Ruskov Technical University - Varna 38
IPC Messages. Example (cont.)// Message-sender process#include <sys/ipc.h>#include <sys/msg.h>...
#define KEY 75#define MSGSIZE 70#define MSGTYPE 5typedef struct msgs {
long mtype;char mtext[MSGSIZE];
} msg_str;
int main (){int msgid;msg_str msg;char str[6]="HELLO";
msgid = msgget(KEY, IPC_CREAT | 0660); // Create message queue and get its IDmsg.mtype = MSGTYPE;strcpy(msg.mtext, str);if (msgsnd(msgid,(struct msgbuf *)&msg, MSGSIZE, 0) < 0) {
perror("msgsnd"); exit(1); }...
}
Trifon Ruskov Technical University - Varna 39
IPC Shared Memory
Shared memory is a mapping of an area (segment) of memory into several process address spaces, so it could be shared by them. This is the fastest form of inter-process communication. Processes access this segment directly by pointers.A segment can be created by one process, and subsequently used by any number of processes.
A process creates a shared memory segment using shmget()int shmget(key_t key, size_t size, int shmflg);
Parameters:key - an user-defined value, associated with a shared memory segmentsize - size in bytes of the requested shared memoryshmflg - specifies the creation control flags and initial access permissions
returns:shmID – shared memory segment identifier on success-1 – otherwise (errno is set)
This call is also used to get the ID of an existing shared segment if calling process has enough permissions.
Trifon Ruskov Technical University - Varna 40
Attaching a Shared Memory Segment
Once a process has a valid IPC identifier for a given segment, its next step is to attach or map the segment into its own address space:
void *shmat(int shmid, const void *shmaddr, int shmflg);
Parameters:shmid - shared memory segment identifier shmaddr – virtual address in process address space where the shared memory is to be mapped. If the shmaddr argument is zero, the kernel tries to find an unmapped region. This is the recommended method.shmflg - specifies the shared memory access mode (SHM_RDONLY –segment is read-only).
returns:address at which segment was attached to the process – on success-1 – otherwise (errno is set)
Trifon Ruskov Technical University - Varna 41
Detaching a Shared Memory Segment
After a shared memory segment is no longer needed by a process, it should be detached by calling shmdt().
int shmdt(const void *shmaddr );
Parameters:shmaddr – shared memory segment address returned by shmat()
returns:0 – on success-1 – otherwise (errno is set)
Trifon Ruskov Technical University - Varna 42
Controlling a Shared Memory Segment
Direct manipulation of internal kernel shared memory structures may be done by:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
Parameters:shmid – a shared memory segment identifier.cmd – one of:
IPC_STAT – retrieves information for a segment, and stores it in the address pointed to by buf.IPC_SET – set the permissions and other information for the shared memory segment.IPC_RMID – marks the segment for removal. The actual removal itself occurs when the last process currently attached to the segment has properly detached it.
buf – pointer to data buffer.returns:
0 – on success-1 – otherwise (errno is set)
Trifon Ruskov Technical University - Varna 43
IPC Shared Memory. Example// Shared memory clear process Pc
#include <sys/ipc.h>#include <sys/shm.h>
...#define SHMKEY 75
int main (){ int shmid;
int *pint;char *addr;
// Create shared memory and get its IDshmid = shmget(SHMKEY, sizeof(int), 0660 | IPC_CREAT);
addr = shmat(shmid, 0, 0); // Attach to the shared memory
pint = (int *)addr;*pint=0; // Clear shared memory
}
P1 P2
integer variable
shared memory
Pc
+1 -1
Trifon Ruskov Technical University - Varna 44
IPC Shared Memory. Example (cont.)// Inter-process communication via shared memory#include <sys/ipc.h>#include <sys/shm.h>...#define SHMKEY 75
int main (){int i, shmid, *pint, status;char *addr;// Create shared memory and get its IDshmid = shmget(SHMKEY, sizeof(int), 0660 | IPC_CREAT);addr = shmat(shmid, 0, 0);pint = (int*)addr;
switch (fork()){ // Fork communicating processescase 0: pint = (int *)addr;
for (i=0;i<5000000;i++) *pint = *pint + 1;break;
default: pint = (int *)addr;for (i=0;i<5000000;i++) *pint = *pint - 1;wait(&status);printf(“Shared memory value is: %d\n”, *pint);
}}
Trifon Ruskov Technical University - Varna 45
IPC Semaphores
Semaphores can be operated as individual units or as elements of a set.A semaphore is represented as:
A value.A count of processes waiting for its value to increase.A count of processes waiting for its value to become 0.An identifier of the last process completed a semaphore operation.
0 1 2 3 4 5 6
0 1 2 3
Arrays of semaphores
0
Semaphore sets table
Trifon Ruskov Technical University - Varna 46
Getting Access to Semaphores
int semget(key_t key, int nsems, int semflag);
Parameters:key – a user defined value, associated with a semaphore set.nsems - specifies the number of semaphores that should be created in a new set.semflag - control flags and settings for the semaphore permissions.
returns:semID – semaphore set identifier on success-1 – otherwise (errno is set)
This system call compares the given key to values that exist within the kernel for other semaphore sets. At that point, the open or access operation is dependent upon the contents of the semflag argument:
IPC_CREAT - create the semaphore set if it doesn’t already exist in the kernel.IPC_CREAT | IPC_EXCL – function fails if the specified semaphore set already exists.
Trifon Ruskov Technical University - Varna 47
Semaphore Operations
Operations on a semaphore set can be performed by:
int semop(int semid,struct sembuf *sops,size_t nsops);
Parameters:semid – semaphore set identifier.sops - pointer to an array of structures, each containing the followinginformation about a semaphore operation:
the semaphore number.the operation to be performed.control flags, if any.
nsops - specifies the length of the array of operations.returns:
0 – on success (all operations performed)-1 – otherwise (errno is set)
Trifon Ruskov Technical University - Varna 48
Semaphore Operations (cont.)
The sembuf structure specifies a semaphore operation:struct sembuf {ushort_t sem_num; /* semaphore number */ short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */
};
Either all operations, specified in sops, are executed, or none (“all or nothing”). If the execution of some sops operation is not possible, the kernel restores the old values of the semaphores and suspends the process.
When the event, on which the process waits, takes place, the semop() system call is restarted and starts its execution from the beginning (i.e. from the first element of sops).
Prior to the execution of each operation, the validity of the specified semaphore and its read/write privileges are checked.
Trifon Ruskov Technical University - Varna 49
Semaphore Operations (cont.)
The semaphore value is changed depending on sem_op:sem_op > 0 – Semaphore value is incremented by the sem_op value
(corresponds to releasing multiple resources). All processes, waiting on semaphore increment are awaken.
sem_op = 0 – The kernel checks the current semaphore value (sem_val). Two cases are distinguished:
sem_val = 0 – The kernel continues with the execution of the remaining operations from sops.sem_val ≠ 0 – Current process is suspended until sem_val becomes 0.
sem_op < 0 – (corresponds to obtaining multiple resources). Two cases:
If |sem_op| <= sem_val, then sem_val := sem_val + sem_op. If sem_val = 0, the kernel wakes all processes, waiting for zero semaphore value.If |sem_op| > sem_val, then kernel suspends the current process until the
semaphore is incremented.
Trifon Ruskov Technical University - Varna 50
IPC Semaphores. Example // Inter-process communication via shared memory// synchronized with semaphores#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>...#define SHMKEY 55#define SEMKEY 81
int main (){int i, shmid, *pint, status;char *addr;short init[1];struct opt {
short sem_num;short sem_op;short sem_flg;
}; struct sembuf p,v;
// Create shared memory and get its IDshmid = shmget(SHMKEY, sizeof(int), 0660 | IPC_CREAT);addr = shmat(shmid, 0, 0); // Attach to the shared memorypint = (int *)addr;*pint=0; // Clear shared memory
P1 P2
integer variable
shared memory
+1 -1
semaphore
Trifon Ruskov Technical University - Varna 51
IPC Semaphores. Example (cont.) // Create and initialize semaphoresinit[0] = 1;semid = semget(SEMKEY, 1, IPC_CREAT | 0660);p.sem_num = 0;p.sem_op = -1;p.sem_flg = 0;v.sem_num = 0;v.sem_op = 1;v.sem_flg = 0;semctl(semid, 1, SETALL, init);
switch (fork()) { // Fork communicating processescase 0: pint = (int *)addr;
for (i=0;i<500000;i++){semop(semid, &p, 1);*pint = *pint + 1;semop(semid, &v, 1);
}break;
default: pint = (int *)addr;for (i=0;i<500000;i++){
semop(semid, &p, 1);*pint = *pint - 1;semop(semid, &v, 1);
}wait(&status);printf(“Shared memory value is: %d\n”, *pint);
}}