Ipc
Ipc
Semaphores - a synchronisation abstraction Monitors - a higher level abstraction Inter-Process Message Passing much more useful for information transfer
can also be used just for synchronisation can co-exist with shared memory communication
message length
data type, data etc.
1
Fixed-length messages:
simple to implement - can have pool of standard-sized buffers
low overheads and efficient for small lengths
- copying overheads if fixed length too long
can be inconvenient for user processes with variable amount of data to pass
may need a sequence of messages to pass all the data long messages may be better passed another way e.g. FTP
- copying probably involved, sometimes multiple copying into kernel and out
Variable-length messages:
more difficult to implement - may need a heap with garbage collection
more overheads and less efficient, memory fragmentation
Issues:
how are links established? can a link be associated with more than two processes? how many links can there be between every pair of processes?
a link established automatically between every pair of processes that want to communicate
processes only need to know each others identity
link is associated with exactly two processes link is usually bidirectional but can be unidirectional
Asymmetric addressing:
only the sender names the recipient recipient not required to name the sender - need not know the sender send ( P, message ) receive ( id, message ) : send message to process P : receive from any process, id set to sender
Indirect communications :
messages sent to and received from mailboxes (or ports)
mailboxes can be viewed as objects into which messages placed by processes and from which messages can be removed by other processes
each mailbox has a unique ID two processes can communicate only if they have a shared mailbox
5
a communications link is only established between a pair of processes if they have a shared mailbox a pair of processes can communicate via several different mailboxes if desired a link can be either unidirectional or bidirectional a link may be associated with more than two processes
allows one-to-many, many-to-one, many-to-many communications
one-to-many : any of several processes may receive from the mailbox e.g. a broadcast of some sort
which of the receivers gets the message?
- arbitrary choice of the scheduling system if many waiting? - only allow one process at a time to wait on a receive
many-to-many :
e.g. multiple senders requesting service and a pool of receiving servers offering service - a server farm
Mailbox Ownership
process mailbox ownership :
only the process may receive messages from the mailbox other processes may send to the mailbox
mailbox can be created with the process and destroyed when the process dies
- process sending to a dead processs mailbox will need to be signalled
Unbounded capacity
any number of messages can be queued - in virtual space?
Copying
need to minimise message copying for efficiency copy from sending process into kernel message queue space and then into receiving process?
probably inevitable in a distributed system advantage that communicating processes are kept separate
- malfunctions localised to each process
8
properties :
processes tightly synchronised - the rendezvous of Ada effective confirmation of receipt for sender at most one message can be outstanding for any process pair
- no buffer space problems
disadvantages :
sending process might want to continue after its send operation without waiting for confirmation of receipt
receiving process might want to do something else if no message is waiting to be received
10
Asynchronous :
send and receive operations non-blocking
sender continues when no corresponding receive outstanding receiver continues when no message has been sent
properties :
messages need to be buffered until they are received
- amount of buffer space to allocate can be problematic - a process running amok could clog the system with messages if not careful
Other combinations :
non-blocking send + blocking receive
probably the most useful combination sending process can send off several successive messages to one or more processes if need be without being held up receivers wait until something to do i.e. take some action on message receipt
- e.g. a server process - might wait on a read until a service request arrived, - then transfer the execution of the request to a separate thread - then go back and wait on the read for the next request
12
Missing messages ?
message sent but never received
receiver crashed? receiver no longer trying to read messages?
Crashing processes :
kernel knows when processes crash can notify waiting process
by synthesised message by signal terminate process
13
Time-outs
add a time-limit argument to receive
receive ( mailbox, message, time-limit )
receiver :
receive (mailbox, message, time-limit) if ( message received in time ) send (ackmail, ackmess)
14
Lost messages
particularly relevant in distributed systems OSs need to be resilient i.e. not crash either the kernel or user processes options:
kernel responsible for detecting message loss and resending
- need to buffer message until receipt confirmed - can assume unreliability and demand receipt confirmation within a time limit
user selection allow receiving process to select which message to receive next
- e.g. from a particular process, to complete some comms protocol
Authentication
of sending and receiving processes - signatures, encryption etc.
16
Mutual Exclusion :
initialise :
create_mailbox (mutex) send (mutex, null-message)
producer :
get a message block from mayproduce
put data item in block send message to mayconsume
consumer :
get a message from mayconsume
consume data in block return empty message block to mayproduce mailbox
18
consumer :
19
properties :
no shared global data accessed all variables local to each process works on a distributed network in principle
sending process changed to reply-blocked state had the receiver issued a receive before sender issued a send, receiver would have gone into receive-blocked state when receiver has processed the data, it issues a reply, which unblocks the sender and allows it to continue
- which process runs first is left to the scheduler
21
messages can be received from either one mailbox or from one of a set of mailboxes port_status call returns number of messages in a queue message transfer done via shared virtual memory if possible to avoid copying
only works for one system, not for a distributed system
23
Shared files :
one process writes / appends to a file other process reads from it properties:
any pair of process with access rights to the file can communicate large amounts of data can be transferred synchronisation necessary
Pipes :
kernel buffers for info transfer, typically 4096 bytes long, used cyclically e.g. used by command shells to pipe output from one command to input of another : $ ls | wc -w
command shell forks a process to execute each command normally waits until sub-process terminates before continuing
- but continues executing if & appended to command line
24
fork returns 0 to child process, sub-process ID to parent by default : write blocks when buffer full, read blocks when buffer empty
25
$ ls | wc -w
ls executed by child process, wc executed by parent process file descriptors manipulated with close() and dup() so that pipe descriptors become standard output to ls and standard input to wc execlp replaces current process with the specified command
26
if ( pipe(fda) < 0 ) error (create pipe failed\n); switch ( fork() ) { // fork an identical sub-process case -1 : error (fork failed\n); case 0: // run ls in child process close (1); // close standard output dup ( fda[1] ); // duplicate pipe write end close ( fda[1] ); // close pipe write end close ( fda[0] ); // close pipe read end execlp (ls, ls, 0); // execute ls command error (failed to exec ls\n); // should not get here break; default:// run wc in parent close (0); // close standard input dup (fda[0] ); // duplicate pipe read end close ( fda[0] ); // close read end of pipe close (fda[1] ); // close write end of pipe execlp (wc, wc, -w, 0); // execute wc command error (failed to execute4 wc\n); break; }
27
example :
#include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #define WRFLAGS (O_WRONLY | O_CREAT | O_TRUNC) #define MODE600 (S_IRUSR | S_IWUSR) main() { close (0); // close standard input if (open(file1, O_RDONLY) == -1) error(open input file failed\n); close (1); // close standard output if (open(file2, WRFLAGS, MODE600) == -1) error(open output failed\n); execlp (cat, cat, 0); // execute cat command
can be opened and used by any process with access permission same functionality as anonymous pipes with blocking by default concurrent writers are permitted writes of up to 4096 bytes are guaranteed to be atomic
Sockets
intended for communications across a distributed network uses the connectionless Internet Protocol and IP addresses at the lowest level e.g. 129.215.58.7 datagram packets transmitted to destination IP host User Datagram Protocol (UDP) or Transmission Control Protocol (TCP) at the application level TCP is a connection based protocol, with order of packet arrival guaranteed a socket is a communication end-point once a TCP-socket connection between two processes is made, end-points made to act like ordinary files, using read() and write() system calls.
30
a Client-Server system :
creating a socket :
- sd = socket ( family, type, protocol );
can be made non-blocking for server to enquire whether any clients waiting
connectionless communication with UDP datagram sockets also possible using sendto() and recvfrom() system calls
31
void close_socket(int sd) { int cs; if ((cs = close(sd)) < 0) { printf(close socket failed: %s\n, strerror(errno)); exit(1); } }
#define SERVER (129<<24 | 215<<16 | 58<<8 | 7) #define MESSAGELEN 1024 #define SERVER_PORT 5000 void main() { int ssd, csd; struct sockaddr_in server, client; int sockaddrlen, clientlen, ca; char message[MESSAGELEN]; int messagelen; sockaddrlen = sizeof(struct sockaddr_in);
32
// create socket if ((ssd = socket (AF_NET, SOCK_STREAM, 0)) < 0) { printf(socket create failed: %s\n, strerror(errno)); exit(1): } else printf(server socket created, ssd = %d\n, ssd);
// bind socket to me server.sin_family = AF_INET; server.sin_port = htons(SERVER_PORT); // big/little-endian conversion server.sin_addr.s_addr = htonl(SERVER); bzero(&server.sin_zero, 8); if (bind(ssd, (struct sockaddr *) &server, sockaddrlen) < 0) { printf(server bind failed: %s\n, strerror(errno)); exit(1): } // listen on my socket for clients if (listen(ssd, 1) < 0) { printf(listen failed: %s\n, strerror(errno)); close_socket(ssd); exit(1); } // make socket non-blocking fcntl(ssd, F_SETFL, fcntl(ssd, F_GETFL) | O_NDELAY);
33
// accept a client (non-blocking) clientlen = sockaddrlen; while ((csd = accept(ssd, &client, &clientlen)) < 0) { if (errno == EAGAIN) { printf(no client yet\n); sleep(1); // wait a sec } else { printf(accept failed: %s\n, strerror(errno)); close_socker(ssd); exit(1); }
ca = ntohl(client.sin_addr.s_addr); printf(client accepted, csd = %d, IP = %d.%d.%d.%d\n, csd, (ca>>24)&255, (ca>>16)&255, (ca>>8)&255, ca&255); // send message to client sprintf(message, Server calling client : hi!\n); messagelen - strlen(message)+1; if (write(csd, message, messagelen) != messagelen) { printf(write failed\n); close_socket(ssd); exit(1); } else printf(message sent to client\n); // receive message from client if (read(csd, message, MESSAGELEN) < 0) { if (errno == EAGAIN) {
34
printf(no client message yet\n); sleep(1); } else { printf(read failed: %s\n, strerror(errno)); close_socket(ssd); exit(1); }
printf(client message was:\n%s, message); close_socket(ssd); }
35
// Client-side socket demo program #include <fcntl.h> #include <linux/socket.h> #include <linux/in.h> #include <errno.h>
void close_socket(int sd) { int cs; if ((cs = close(sd)) < 0) { printf(close socket failed: %s\n, strerror(errno)); exit(1); } } #define SERVER (129<<24 | 215<<16 | 58<<8 | 7) #define MESSAGELEN 1024 #define SERVER_PORT 5000 void main() { int ssd, csd; struct sockaddr_in server, client; int sockaddrlen, clientlen, ca; char message[MESSAGELEN]; int messagelen; sockaddrlen = sizeof(struct sockaddr_in);
36
//create socket if ((csd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf(client socket create failed: %s\n, strerror(errno)); exit(1); } else prinf(client socket create, csd = %d\n, csd);
// try to connect to server if (connect(csd, (struct sockaddr *) &server, sockaddrlen) < 0) { printf(connect failed: %s\n, strerror(errno)); // need to destroy socket before trying to connect again close_socket(csd); sleep(1); } else break; } printf(connected to server\n); // make socket non-blocking fcntl(csd, F_SETFL, fcntl(csd, F_GETFL) | O_NDELAY);
37
// receive a message from server while (read(csd, message, MESSAGELEN) < 0) { if (errno == EAGAIN) { printf(no server message yet\n); sleep(1); } else { printf(read failed: %s\n, strerror(errno)); close_socket(csd); exit(1); } } printf(server message was:\n%s, message);
// send a message to server sprintf(message, Client calling server : ho!\n); messagelen = strlen(message)+1; if (write(csd, message, messagelen) != messagelen) { printf(write failed\n); close_socket(csd); exit(1); } else printf(message sent to server\n); close_socket(csd); }
38
Signals
the mechanism whereby processes are made aware of events occurring asynchronous - can be received by a process at any time in its execution examples of Linux signal types: SIGINT : interrupt from keyboard SIGFPE : floating point exception SIGKILL : terminate receiving process SIGCHLD : child process stopped or terminated SIGSEGV : segment access violation default action is usually for kernel to terminate the receiving process process can request some other action ignore the signal - process will not know it happened
- SIGKILL and SIGSTOP cannot be ignored
39
- when the handler returns, control is passed back to the main process code and normal execution continues
example:
gets characters until a newline typed, then goes into an infinite loop uses signals to count ctrl-cs typed at keyboard until newline typed
40
see also the POSIX sigaction() call - more complex but better
41