Interprocess Communication(IPC)
why:
--> 1.processes run in separate address spaces; one process acnnot directly access the memory that another proces has writen to.
2.Processes need some way to communicate
how:
--> Signals,Pipes,Shared memory(sockets,etc.)
Signals:
1.to notify process es when certain events occur
2.can be used by user processes to communicate with each other
3.donot allow process to specify >1 word of data to exchange with other processes
4.created by the kernel in response to unterrupts and exceptions, are sent to a process or thread
-as a result of executing an instructions;
-from another process
-from an asynchronous event
5. some common linux siganls
SIGSEGV: invalid memory segment access or also called segmentation fault
SIGBUS: bus error
SIGSTOP: stop executing, pause
SIGCONT: continue paused process
SIGKILL: kill target process.
SIGUSR1 and SIGUSR2: user defined signals
SIGPIPE: Write on a pipe with no reader, broken pipe.
6.handle signal by
a.ignore the signal--processes can ignor all but SIGSTOP and SIGKILL signals
b.catch the signal-- when a process catches a signal,it invokes its signla handler to respond to the signal
c.execute the default action that the kernel defines for that signal
e.g.
#include<signal.h>
// signal handler
void sigprintchild() {/* routines child will call upon sigtrap */
printf ("This output comes from the child process\n");
}
int main (void)
{
pid_t pid1; /* variable to record process id of child */
pid1 = fork(); /* create child 1 */
if (pid1 == -1) /* check for error in spawning child process */
{
perror ("error in fork");
exit (1);
}
if (pid1 == 0) /* check if this is the new child process */
{ /* processing for child 1 */
signal(SIGUSR1,sigprintchild); // register the signal handler sigprintchild with the signal SIGUSR1
pause();
}
else {
printf ("This output comes from the parent process.\n");
kill(pid1,SIGUSR1); // sends the signal SIGUSR1 for process with PID pid1
}
}
signal system call: -must define signal handler to respind to signals ; two params,first specifies the signal handler to be used
kill to send a signal to a process and first param is pid that signal is to be sent to, second specified the particular to be sent
Pipes:
1. Message passing:
a.msg can be passed in one direction at a time (one process is sender and the other is receiver)
b.msg passing can be bidirectional(one process can act as either sender or receiver)
c.Msg can be blocking or nonblocking
-blocking need receiver to notify the sender when msg is received
-nonblocking enables the sender to continue with other process .
d.Implementation: pipe
2.Pipe
a.a region of memory protected by the OS that serves as a
buffer allowing >=2 processes to excahnge data
b. producer process writes data to the pipe,a/f consumer process reads data from the pipe in FIFO order
c.Access to pipess controlled by file descriptors(can be passed b/t related processes,like parent n child)
d.supports both blocking and nonblocking pipes
e.limitation:only half-duplex ;only be used b/t processes with a common acestor;fixed-size buffer
e.g.
int pipe(int fd[2])
--file desciptor fd[0] is open for reading,f[1] is open for writing; return 0 is OK ,-1 on error
/* This program creates a new process and provides a simple pipe to
allow the parent to communicate with the child
Version 1 -- explicitly using pipe and byte-oriented read/write */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#define MAX 40 /* maximum number of letters communicated */
int main (void)
{ int fd[2]; /* provide file descriptor pointer array for pipe */
/* within pipe:
fd[0] will be input end
fd[1] will be output end */
pid_t pid;
char line[MAX]; /* character array (string) for reading */
if (pipe (fd) < 0) /* create pipe and check for an error */
{ perror("pipe error");
exit (1);
}
if ((pid = fork()) < 0) /* apply fork and check for error */
{ perror ("error in fork");
exit (1);
}
if (0 == pid)
{ /* processing for child */
printf ("The child process is active.\n");
close (fd[1]); /* close output end, leaving input open */
read(fd[0], line, MAX);
printf ("The string received is '%s'\n", line);
}
else
{ /* processing for parent */
printf ("The parent process is active.\n");
close (fd[0]); /* close input end, leaving output open */
write (fd[1], "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26);
write (fd[1], "abcdefghijklmnopqrstuvwxyz", 26);
/* print string and indicate byte length */
}
exit (0); /* quit by reporting no error */
}
Shared Memory
1.adv. improve performance for process that frequently access shared data;process can share as
much data as they can address; unlike pipes the processes do not have to related
2.processes share regions of memory and map that memory to each process virtual add. space
3.standard interfaces: system V shared mem; POSIX shared mem
4. system call
int shmget(key_t key, size_t size, int shmflg)
a.create shared mem.
b.Returns the id of the shared memory fragment
c.The key parameter is a name you give to the shared memory segment
d.Size is the size of the shared memory segment in bytes.
e.The shmflg argument specifies the initial access permissions and creation control flags
-- IPC_CREAT : create a new shared memory segment.
-- IPC_EXCL: used with IPC_CREAT to ensure failure if segment already exists.
if flag is not specified finds the segment associated with key
mode_flags used to specify permissions.
void *shmat(int shmid, const void *shmaddr, int shmflg);
a.Used to attach a shared memory specified by shmid to a particular part of the process’s virtual address space
b.Returns the virtual address that the shared memory is attached to.
c. shmid : shared memory id
d. shmaddr: NULL value means attach shared at some system determined unused space.
If an address is specified then process will try to attach at the specified address.
e. shmflg: SHM_RDONLY attached for reading only.
e.g.
main() {
char c;
int shmid;
key_t key = 1234; // we name our shared memory segment “1234”
char *shm, *s;
/* Create the segment. */
if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
perror("shmget");
exit(1);
}
/* Now we attach the segment to our data space. */
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
{ perror("shmat");
exit(1); }
/* Now put some things into the memory for the other processes to read. */
s = shm;
for (i = 0; i < 26; i++)
s[i] = ‘a’ + i;
s[26] = NULL;
}