Slides: Sysprog: POSIX IPC¶
Unix IPC: mechanisms to communicate between unrelated* processes
Semaphores
Shared memory
Message queues
No sockets
History: Two IPC Variants¶
System V IPC
Cumbersome, unnecessarily complex API
Older -> more portable between Unixen
POSIX IPC
Easy to use
Much of it implemented in userspace (through memory mapped files)
Optional feature in POSIX (fully supported in Linux though)
Object Names¶
Communication between unrelated processes
Related: none is a descendant of the other (
fork()
)Cannot inherit object
Must be able to locate them
System-wide visibility via names
Just like files
In fact, most IPC mechanisms are files (at least in Linux)
Consistently with leading slash:
/some-object-name
File Semantics¶
Objects look just like files. For example,
shm_open()
, using the same flags as good ol’open()
shm_unlink()
to remove a shared memory segment, just like good ol’unlink()
removes a file.
Handles are reference counted
Shared memory:
int
- a true file descriptorMessage queue:
mqd_t
(typedefint
)Incremented across
fork()
,dup()
etc.
Message Queues¶
Message queue parameters
Maximum number of messages
Maximum size of a single message
Realtime guarantees
Message priorities
Messages are sent with a priority
Higher prioritized messages overtake lower prioritized messages
Open/Create: mq_open()
¶
mqd_t mq_open(const char *name, int oflag);
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
Attributes (
attr
)mq_flags
: nonblocking?mq_maxmsg
: lengthmq_msgsize
: width
Sending/Receiving: mq_send()
, mq_receive()
¶
int mq_send(mqd_t mqdes, const char *msg_ptr,
size_t msg_len, unsigned msg_prio);
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,
size_t msg_len, unsigned *msg_prio);
Higher with higher priority are faster
msg_len
must not exceed configured queue widthSame as
write()
/send()
otherwise
Closing/Removing: mq_close()
, mq_unlink()
¶
int mq_close(mqd_t mqdes);
int mq_unlink(const char *name);
Boring …
Analogy:
close()
andunlink()
.
Notification: mq_notify()
¶
int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
Obscure feature …
Only shown because of its obscurity
Specification predates that of event loops
Guess what … SIGNALS
Please read yourself and be disturbed!
Message Queues are Files¶
Obvious implementation: files
… provided there’s OS infrastructure
Message queues are implemented as files
Virtual filesystem -
mqueue
Notifications can be received more elegantly - select()
,
poll()
, epoll
!
Message Queue Filesystem: mqueue
¶
Message queues visible as files: the mqueue filesystem
# mount -t mqueue blah /mnt/mqueue
# ls -l /mnt/mqueue/my-queue
-rw------- ... /mnt/mqueue/my-queue
# cat /mnt/mqueue/my-queue
QSIZE:0 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
Semaphores¶
Communication and synchronization device
Bag of N elements
N items can be consumed without waiting
(N+1)st consumer has to wait until an item is goiven back
Creation parameter
Initial value N
Open/Create: sem_open()
¶
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag,
mode_t mode, unsigned int value);
Again: file semantics
Like
open()
, to calling “signatures”create
open
value
: initial value N (creation only)
Communication: sem_wait()
, sem_post()
¶
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
int sem_post(sem_t *sem);
wait: consume element; blocks if count is zero
post: give element back
Closing/Removing: sem_close(), ``sem_unlink()
¶
int sem_close(sem_t *sem);
int sem_unlink(const char *name);
Boring (again) …
Analogy:
close()
andunlink()
.
Semaphores are Files¶
$ ls -l /dev/shm/
total 1604
-rw------- ... sem.my-semaphore
/dev/shm
is atmpfs
instancesem.my-semaphore
is a regulare file in itContains a flat structure, the semaphore
sem_t
encapsulates open file descriptor andvoid*
(the mapped memory)
Exercise: POSIX Message Queues¶
Add a POSIX message queue to our server like follows
The client (to be written) opens an existing message queue, sends a message, and closes the queue afterwards.
The server
creates the message queue in the startup phase
receives (file descriptor based) notifications in the main loop, and reads and outputs messages just like the others
closes and removes the queue in the shutdown phase