Interprocess Communication

advertisement
Interprocess Communication
●
●
Originally multiple approaches
Today – more standard – some differences between
distributions still exist
Pipes
●
Oldest form of IPC – provided by all distros
●
Limitations
●
–
Historically half-duplex (data moves in only 1 direction)
–
Can only be used between processes that have a common
ancester
–
Normally created by parent – parent forks child – used
between parent & child
Most commonly used form of IPC
Pipes
●
●
Sequence of commands in a pipeline for shell to
execute
–
Shell creates a separate process for each command
–
Links standard output of one process to standard input
of next process using a pipe
int pipe (int fd[2]);
–
2 file descriptors are returned through fd argument
●
●
fd[0] – open for reading
fd[1] – open for writing
Pipes
Pipes
●
fstat function – returns file type of pipe (FIFO)
●
Can test for a pipe with S_ISFIFO macro
Pipes
For a pipe from child to parent, parent closes fd[1]
& child closes fd[0]
Pipes
●
●
When 1 end of the pipe is closed
–
If read is done from a pipe whose write end has been
closed – read returns a 0
–
If write is done to a pipe whose read end has been
closed, signal SIGPIPE is generate
PIPE_BUF – specifies pipe buffer size
Pipes
●
Can use 2 pipes for parent/child synchronization
popen & pclose functions
●
●
●
●
FILE* popen (const char* cmdsring, const char*
type);
int pclose (FILE* f);
Functions in stdio that open & close pipes – handle
all the details (fork, exec, …)
Pclose – closes standard I/O stream – waits for
command to terminate – returns termination status
to shell
FIFOs
●
●
Named pipes
Unnamed pipes – can only be used between related processes
with a common ancestor creating the pipe
●
FIFOs – unrelated processes can exchange data
●
int mkfifo (const char* path, mode_t mode);
●
int mkfifoat (int fd, const char* path, mode_t, mode);
●
Similar to creating a file
●
After fifo has been created, open function to open it
●
Normal file I/O functions used with FIFOs
FIFOs
●
Nonblocking flag (O_NONBLOCK)
–
Not used when opening
●
●
–
Used when opening
●
●
●
Open for read-only blocks until a different process opens FIFO
for writing
Open for write-only blocks until a different process opens
FIFO for reading
Open for read-only returns immediately
Open for write-only returns -1 & sets error flat if no process
has the FIFO open for reading
Write to FIFO that has no process open for reading
– SIGPIPE is generated
FIFOs
●
Common to have multiple writers for a FIFO
–
●
Have to worry about atomic writes
Uses for FIFOS
–
Shell commands to pass data from one shell pipeline to
another
–
Rendezvous points in client-server applications
Using FIFOs to Duplicate Output
Streams
●
●
FIFOs cannot be used for nonlinear connections
since they have names
Tee – copies standard input to both standard output
& file named on command line
mkfifo fifo1
prog3 < fifo1 &
prog1 < infile | tee fifo1 | prog2
Client-Server Communication
using a FIFO
●
●
Each client can write its request to a known FIFO
for the server
Requests need to be < PIPE_BUF bytes
Client-Server Communication
using a FIFO
●
●
●
Problem – how to send responses back to client
Cannot use a single FIFO – clients would not know
when to get response
One possibility – send process id with request –
server create a FIFO for each client
–
Server cannot tell whether client crashes
XSI IPC
●
●
●
IPC structures
–
Message queues
–
Semaphores
–
Shared memory segment
Each IPC structure – has non-negative integer
identifier – internal name for IPC object
Cooperating processes need an external naming
scheme to be able to access each other
–
Each IPC object has a key – acts as external name
XSI IPC
●
Client server rendezvous techniques
–
Server can create a new IPC structure by specifying a key of
IPC_PRIVATE – store
●
●
–
Client & server – agree on a key by defining the key in a
common header
●
●
–
IPC_PRIVATE – guarantees new IPC structure is created
Disadvantage – file system operations are required for server to
write integer identifier to a file & for clients to retrieve this
identifier
Server creates IPC structure specifying this key
Potential problem – possible for key to already be associated with
an IPC structure
Client & server – agree on a pathname & project ID – call
ftok to convert these values to a key
Permission Structure
●
ipc_perm structure associated with each IPC
structure
struct ipc_perm {
uid_t uid; /* owner's effective user id */
gid_t gid; /* owner's effice group id */
uid_t cuid; /* creator's effective user id */
git_t cgid; /* creator's effective group id */
mode_t mode; /* access modes */
...
}
●
●
Each implementation has additional members
Fields initialized when IPC structure is created
Advantages & Disadvantages
●
IPC structures are systemwide & do not have
reference count
–
●
Remain in system until explicitly deleted
IPC structures not known by names in file system
–
Cannot access them using file operations
Message Queues
●
Linked list of messages stored with kernel
●
Identified by message queue identifier (queue ID)
●
Created by msgget function
●
Messages added at end by msgsnd function
●
Messages fetched by msgrcv function
–
●
Can fetch messages by type instead of FIFO
Message consists of
–
Positive long integer type field
–
Non-negative length
–
Actual data
System Limits
Message Queues
●
●
int msgget (key_t key, int flag);
–
Open existing queue or create new queue
–
Queue ID is returned
msgctl (int msqid, int cmd, struct msquid_ds *buf);
–
Performs various operations on a queue – cmd
●
●
●
●
IPC_STAT – fetch msqid_ds structure for queue – storing in buf
IPC_SET – copy fields from buf to msqid_ds structure
IPC_RMID – remove message queue from system – includes any data still
on the queue
int msgsnd (int msqid, const soid* ptr, size_t nbytes, int flag);
–
Data placed on message queue
–
ptr – points to long integer followed by message data
Message Queues
●
ssize_t msgrcv (int msqid, void* ptr, size_t nbytes,
long type, int flag)
–
Retrieve message from queue
–
type – specify which message
●
●
●
type == 0 – first message
type > 0 – first message whose type is argument type
type < 0 – first message whose type is lower than argument
type
–
flag – IPC_NOWAIT – operation nonblocking
–
When operations succeeds – kernel updates msqid_ds
structure
Semaphores
●
Counter used to provide access to shared resource
–
Test semaphore that controls resource
–
If value > 0
●
●
–
If value = 0
●
●
●
process can use resource
Value decremented
Process goes to sleep until semaphore value > 0
Returns to first step
When process is finished with shared resource –
value incremented & processes waiting for
resources are awakened
Semaphores
●
Test of semaphores value & decrementing value –
must be atomic
–
●
Normally implemented in kernel
Binary semaphore – controls single resource –
value initialized to 1
XSI Semaphores
●
More complicated
–
Not simply a single non-negative value
●
–
–
Set of 1 or more semaphores
Creation of semaphore is independent of its
initialization
Have to worry about a program that terminates without
releasing semaphores it has been allocated
XSI Semaphores
●
●
int semctl (int semid, int semnum, int cmd, …);
–
Catchall for various semaphore operations
–
Last argument union of command specific arguments
–
Optional
int semop (int semid, struct sembuf semoparray[],
size_t nops);
–
Atomically performs an array of operations on a
semaphore set
–
semoparray – pointer to an array of semaphore
operations
–
nops – number of operations
XSI Semaphores
●
●
Operation on each member of the set – specified by
sem_op value
–
Positive – number of resources being returned by the process value of sem_op added to semaphore's value
–
Negative – want to obtain resources that semaphore controls
–
Zero – process wants to wait until semaphore's value becomes 0
Semaphore adjustment on exit
–
If SEM_UNDO flag is set, kernel remembers the resources
allocated from that semaphore
–
When process terminates – kernel makes adjustments to
semaphore counts
XSI Semaphores
●
Methods of handling shared resources
–
Semaphores
–
Record locking
–
mutex
Shared Memory
●
●
●
●
Allows 2 or more processes to share a region of
memory
Fastest form of IPC – data does not need to be
copied
Need to synchronize access
XSI shared memory – anonymous memory
segments
Shared Memory
●
int shmget (key_t key, size_t size, int flag);
–
●
Obtain a shared memory identifier
int shmctl (int shmid, int cmd, struct shmid_ds *buf);
–
Catchall for various shared memory operations
–
cmd
●
●
●
●
●
IPC_STAT – fetch shmid_ds structure for segment & store it in buf
IPT_SET – set 3 fields in structure pointed to by buf
IPC_RMID – remove shared memory segment from system
SHM_LOCK – lock shared memory segment in memory
SHM_UNLOCK – unlock shared memory segment in memory
Shared Memory
●
void* shmat (int shmid, const void* addr, int flag);
–
Process attaches to shared memory segment to its
address space
●
●
●
Addr == 0 – segment is attached to first available address
selected by kernel
addr != 0 & SHM_RND not specified – segment is attached
at address given by addr
addr != 0 & SHM_RND is specified – segment is attached at
address given by (addr – (addr modulus SHMLBA))
–
SHMBLA – low boundary address multiple – power of 2
–
for portability – should not specify address – instead
put 0 & let system choose address
–
Address is returned
Shared Memory
●
int shmdt (const void* addr);
●
Detaches memory segment
Shared Memory
●
●
/dev/zero
–
Provides unbounded supply of null characters
–
Writing to it has no effect
Memory mapping of /dev/zero
–
Unnamed memory region created whose size is the second
argument to mmap rounded to nearest page size
–
Memory region is initialized to 0
–
Multiple processes can share this region if a common
ancestor specifies th MAP_SHARED flag to mmap
POSIX Semaphores
●
●
Address several deficiencies with XSI semaphores
–
Higher performance implementations
–
Simpler to use
–
Behave better when removed
Named & unnamed versions
–
Differ in how they are created & destroyed
–
Unnamed can only be used by threads in the same
process
POSIX Semaphores
●
sem_t sem_open (const char* name, int oflag, …,
unsigned int value);
–
●
Only first 2 arguments unless creating a semaphore –
then need 2 more (mode & initial value)
Portability naming requirements
–
First character should be '/'
–
No other characters should be '/'
–
Max length – implementation defined
POSIX Semaphores
●
int sem_close (sem_t* sem);
–
●
Kernel will close open semaphores if this method is not called
int sem_unlink (const char* name);
–
Destroys a semaphore – deferred until last open reference is closed
●
int sem_trywait (sem_t* sem);
●
int sem_wait (sem_t* sem);
●
int sem_timedwait (sem_t* restrict sem, const struct
timespec* restrict tsprt);
–
Decrements value of semaphore
–
sem_wait blocks but sem_trywait does not
–
sem_timedwait – block for a specified amount of time
POSIX Semaphores
●
int sem_post (sem_t* sem);
–
●
●
int sem_init (sem_t* sem, int pshared, unsigned int value);
–
Creates unnamed semaphore
–
pshared – whether semaphore is to be used with multiple processes
Int sem_destroy (sem_t* sem);
–
●
Increments value
Destroys unnamed semaphore
Int sem_getvalue (sem_t* restrict sem, int* restrict valp);
–
Retrieves value of semaphore – valp
–
Need to use synchronization
POSIX Semaphores
Download