\documentclass[11pt]{beamer}

%\usepackage{ngerman}
\usepackage{times}
\usepackage{graphicx}
\usepackage{pgf,pgfarrows,pgfnodes,pgfautomata,pgfheaps}
\usepackage{amsmath,amssymb}
\usepackage[utf8]{inputenc}
\usepackage{listings,color}
\definecolor{lbcolor}{RGB}{255,210,150}
\lstset{
	language=C,
	numbers=left,
	stepnumber=1,
	numbersep=5pt,
	numberstyle=\tiny,
	breaklines=true,
	breakautoindent=true,
	postbreak=\space,
	tabsize=2,
	basicstyle=\ttfamily\fontsize{7}{9}\selectfont,
	showspaces=false,
	showstringspaces=false,
	extendedchars=true,
	backgroundcolor=\color{lbcolor},
	keywordstyle=\bf ,
	commentstyle=\color{green},
	stringstyle=\color{red}
}

\mode<presentation>
{
	\usetheme{linutronix}
}

% on the following slides, include icon in the left sidebar
\def\lximg{/usr/share/lx/icons/fueller.png}

\title{POSIX IPC}
\institute{Linutronix GmbH}

\begin{document}

\frame{ \titlepage }

% stop displaying 'fueller.png' on the following slides
\def\lximg{none}

%\AtBeginSection[]
%{
%	\begin{frame}<beamer>
%		\tableofcontents[currentsection,currentsubsection]
%	\end{frame}
%}

\AtBeginSubsection[]
{
	\begin{frame}<beamer>
		\tableofcontents[currentsection,currentsubsection]
	\end{frame}
}

\begin{frame}
	\tableofcontents
\end{frame}

\begin{frame}
\frametitle{POSIX IPC: Übersicht}
\begin{itemize}
\item Message Queues
\item Semaphores
\item Shared Memory
\end{itemize}
\end{frame}

\section{Message Queues}
\begin{frame}
\frametitle{POSIX Message Queues}
\begin{itemize}
\item Austausch von Daten in Form von Messages
\item Messages sind priorisierbar
\item Höchste Priorität wird zuerst ausgeliefert
\item Virtuelles Filesystem unter /dev/mqueue
\end{itemize}
\end{frame}


\begin{frame}[fragile]
\frametitle{POSIX Message Queues: API}
Message Queue öffnen / neu anlegen:
\begin{lstlisting}
   #include <fcntl.h>
   #include <sys/stat.h>
   #include <mqueue.h>
   
   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);
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{POSIX Message Queues: API}
Message Queue schliessen:
\begin{lstlisting}
   #include <mqueue.h>
 
   mqd_t mq_close(mqd_t mqdes);
\end{lstlisting}
Message Queue löschen:
\begin{lstlisting}
   #include <mqueue.h>

   mqd_t mq_unlink(const char *name);
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{POSIX Message Queues: API}
Messages senden:
\begin{lstlisting}
#include <mqueue.h>

mqd_t mq_send(mqd_t mqdes, const char *msg_ptr,
              size_t msg_len, unsigned msg_prio);

#define _XOPEN_SOURCE 600
#include <time.h>
#include <mqueue.h>

mqd_t mq_timedsend(mqd_t mqdes, const char *msg_ptr,
              size_t msg_len, unsigned msg_prio,
              const struct timespec *abs_timeout);
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{POSIX Message Queues: API}
Messages empfangen:
\begin{lstlisting}
#include <mqueue.h>

ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,
               size_t msg_len, unsigned *msg_prio);

#define _XOPEN_SOURCE 600
#include <time.h>
#include <mqueue.h>

ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr,
               size_t msg_len, unsigned *msg_prio,
               const struct timespec *abs_timeout);
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{POSIX Message Queues: Beispiel}
Sender:
\begin{lstlisting}
const char message[] = "Hallo\0";
mqd_t ret;

mqd_t mq = mq_open ("/my_queue", O_RDWR |
                     O_CREAT | O_EXCL, 0664, NULL);
if (mq < 0) {
        perror("Can't open message queue\n");
        exit(1);
}

ret = mq_send(mq, message, sizeof(message), 100);
if(ret < 0)
        perror("Can't send message\n");

mq_close(mq);
return 0;
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{POSIX Message Queues: Beispiel}
Empfänger:
\begin{lstlisting}
char message[8192];
unsigned prio;
mqd_t ret;

mqd_t mq = mq_open ("/my_queue", O_RDONLY);
if(mq < 0) {
   perror("Can't open message queue\n");
   exit(1);
}

ret = mq_receive(mq, message, 8192, &prio);
if (ret < 0)
   perror("Nothing to receive\n");
else
   printf("Received message %s with prio %u\n", message, prio);

mq_close(mq);
mq_unlink("/my_queue");
return 0;
\end{lstlisting}
\end{frame}

\section{Semaphoren}
\begin{frame}
\frametitle{POSIX Semaphoren: Übersicht}
\begin{itemize}
\item Synchronisation von Threads und Prozessen
\item Named Semaphores
\item Unnamed Semaphores (memory based)
\item Virtuelles Filesystem unter /dev/shm
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Named Semaphores: API}
Semaphore öffnen / neu erstellen:
\begin{lstlisting}
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag,
                mode_t mode, unsigned int value);

\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Named Semaphores: API}
Unlock auf Semaphore:
\begin{lstlisting}
#include <semaphore.h>

int sem_post(sem_t *sem);
\end{lstlisting}
Lock auf Semaphore:
\begin{lstlisting}
#include <semaphore.h>

int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Named Semaphores: API}
Semaphore schliessen:
\begin{lstlisting}
#include <semaphore.h>

int sem_close(sem_t *sem);
\end{lstlisting}
Semaphore löschen:
\begin{lstlisting}
#include <semaphore.h>

int sem_unlink(const char *name);
\end{lstlisting}
\end{frame}

\begin{frame}
\frametitle{Unnamed Semaphores: Übersicht}
\begin{itemize}
\item Liegen in einem gemeinsamen Speicherbereich (z.B. Shared Memory)
\item Müssen mit sem\_init() initialisiert werden
\item Lock und Unlock mit sem\_post() und sem\_wait()
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Unnamed Semaphores: API}
Initialisieren:
\begin{lstlisting}
#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);
\end{lstlisting}
Zerstören:
\begin{lstlisting}
#include <semaphore.h>

int sem_destroy(sem_t *sem);
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Semaphoren: Beispiel}
\begin{lstlisting}
sem_t *my_sem;
int ret;

my_sem = sem_open("/my_sem", O_RDWR | O_CREAT | O_EXCL, 0644, 0);
if (my_sem == SEM_FAILED) {
        perror("Can't open semaphore\n");
        exit(1);
}

ret = sem_wait(my_sem);
if(ret < 0) {
        perror("sem_wait failed\n");
        exit(1);
}
printf("Here I am :)\n");

sem_close(my_sem);
return 0;
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Semaphoren: Beispiel}
\begin{lstlisting}
sem_t *my_sem;
int ret;

my_sem = sem_open("/my_sem", O_RDWR);
if(my_sem == SEM_FAILED) {
        perror("Can't open semaphore\n");
        exit(1);
}

ret = sem_post(my_sem);
if (ret < 0)
        perror("sem_post\n");

sem_close(my_sem);

return 0;
\end{lstlisting}
\end{frame}

\section{Shared Memory}
\begin{frame}
\frametitle{Shared Memory: Übersicht}
\begin{itemize}
\item Gemeinsam genutzter Speicherbereich
\item mmap()
\item Virtuelles Filesystem unter /dev/shm
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Shared Memory: API}
Shared Memory anlegen / zerstören
\begin{lstlisting}
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

int shm_open(const char *name, int oflag, mode_t mode);

int shm_unlink(const char *name);
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Shared Memory: Beispiel}
\begin{lstlisting}
   int fd; int ret = 1; char *addr;
   
   fd = shm_open("my_shm", O_RDWR | O_CREAT, 0777);
   if (fd < 0) {
   	perror("Can't open Shared Memory\n");
   	goto out;
   }
   if (ftruncate(fd, 4096) == -1) {
   	perror("ltrunc\n");
   	goto out;
   }
   addr = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
   if (addr == MAP_FAILED) {
   	perror("mmap() failed\n");
   	goto out;
   }
   ret = 0;
   *addr = 'A';
out:
   close(fd);
   return ret;
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Shared Memory: Beispiel}
\begin{lstlisting}
   int fd;
   int ret = 1;
   char *addr;
   
   fd = shm_open("my_shm", O_RDWR, 0777);
   if (fd < 0) {
   	perror("Can't open Shared Memory\n");
   	goto out;
   }
   
   addr = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
   if (addr == MAP_FAILED) {
   	perror("mmap() failed\n");
   	goto out;
   }
   printf("Reading from SHM -> %c\n", *addr);
   ret = 0;
out:
   close(fd);
   return ret;
\end{lstlisting}
\end{frame}
\end{document}
