diff --git a/20220516/bs-20220516.txt b/20220516/bs-20220516.txt
new file mode 100644
index 0000000000000000000000000000000000000000..59658174ef708d8d7444ab370b49678f0c4840bf
--- /dev/null
+++ b/20220516/bs-20220516.txt
@@ -0,0 +1,256 @@
+Verwaltung von Arbeitsspeicher (RAM), 16.05.2022, 11:38:16
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+8086: 16-Bit-Intel-Prozessor (Mitte der 1980er Jahre):
+
+  Speicheradresse: xxxx:xxxx, z.B. 31d6:0100 oder b800:0300
+                   ~~~~ ~~~~
+               Segment    Offset   <-- jeweils 16 Bit
+
+  Adressierbarer Speicher: 1 MiB = 1024 kiB = 2^20 Bytes
+  Register: nur 16 Bit, nicht 20
+
+  Speicheradresse = 16 · Segment + Offset
+
+  z.B.: 31d6:0100 = 16 · 31d6 + 0100 = 31d60 + 0100 = 31e60
+
+  Praktischer Sinn: Relokation
+   - 16-Bit-Programme können über 64 kiB (= 65536 Bytes) frei verfügen
+   - Ansprechen dieser 64 kiB nur über Offset-Adresse
+   - Das Betriebssystem teilt die Segment-Adresse zu
+  --> Das Anwendungsprogramm kann ohne Änderung
+      an jeder beliebigen Stelle im Speicher laufen ("Relokation").
+  --> Der Prozessor sieht für das Programm bis zu 4 Segmente vor:
+      Code, Daten, Stack, "Extra" --> zusammen 256 kiB
+
+  Sobald dies nicht mehr genügte, nahmen die Programme eigenständig
+  weitere Segmente hinzu. --> volle 1024 kiB ansprechbar
+  --> Unterlaufen der Zuweisung durch das Betriebssystem
+  --> instabil
+
+  Hätten sich die Programme an die Zuweisung durch das Betriebssystem gehalten,
+  wären sie voreinander abgeschottet gewesen.
+
+80286: 16-Bit-Intel-Prozessor mit "Protected Mode" (Ende der 1980er Jahre):
+
+  Speicheradresse: xxxx:xxxx
+                   ~~~~ ~~~~
+              Selektor    Offset   <-- jeweils 16 Bit
+
+  Der Selektor ist ein Index für ein Array,
+  das sich im Prozessor befindet.
+  Darin enthalten:
+   - tatsächliche Speicheradresse des Segments (auch über 1 MiB hinaus)
+   - Größe des Segments
+   - Zugriffsrechte, z.B.: nur lesbar, ausführbar
+  --> Die Hardware kann die Programme voreinander abschotten (daher "protected").
+      Das Betriebssystem nutzt dies nicht, um sich gegen Programme abzuschotten.
+
+  Nachteil: Offset nur 16 Bit --> Beschränkung auf 256 kiB
+  Umgehung: Das Programm selbst verwaltet die Selektoren.
+  --> "protected" hinfällig
+
+  (Es gab verschiedene Standards, um auf mehr als 1024 kiB zuzugreifen:
+  HMA, XMS, EMS, DPMI)
+
+  Zum Gruseln: HMA
+   - setze das Segment auf 0xffff
+   - sorge per Selektor dafür, daß damit die ersten 64 kiB
+     oberhalb von 1024 kiB angesprochen werden können
+  --> zusätzliche 64 kiB an Speicher nutzbar
+
+80386: 32-Bit-Intel-Prozessor mit "Protected Mode" (1990er Jahre):
+
+  Speicheradresse: xxxx:xxxxxxxx
+                   ~~~~ ~~~~~~~~
+              Selektor    Offset   <-- 16 bzw. 32 Bit
+
+  Der Selektor ist ein Index für ein Array,
+  das sich im Prozessor befindet (wie beim 80286).
+
+  Das Offset ist 32 Bit breit und kann daher bis zu 4 GiB ansprechen. :-)
+
+  --> Das Betriebssystem weist dem Programm ein Segment bis zu 4 GiB zu
+      und schottet es gegenüber sich selbst und anderen Programmen ab.
+      (Bei OS/2 und Unix: von Anfang an; bei MS Windows: ab NT 4.0 bzw. XP)
+
+Im "Protected Mode" möglich: Speicher auf Datenträger auslagern
+
+  Die Tabelle vergibt Segmente auch in Speicherbereichen,
+  die physikalisch gar nicht vorhanden sind.
+
+  Sobald das Programm darauf zugreift, entsteht eine Ausnahmesituation (ähnlich Interrupt).
+  Das Betriebssystem kann darauf reagieren und das Segment physikalischem Speicher zuordnen.
+  Falls kein freier physikalischer Speicher mehr vorhanden ist, kann das Betriebssystem
+  ein anderes Segment auf Datenträger schreiben, dieses auf nicht vorhandenen Speicher
+  umlegen und den dadurch gewonnenen Speicher für das andere Programm nutzen ("Swappen").
+
+  Inhalt der Tabelle ("Deskriptoren"):
+   - Länge des Segments
+   - Start-Adresse
+   - Zugriffsrechte
+      - Nur Kernel? Benutzerprogramme?
+      - Leserecht
+      - Schreibrecht
+      - Ausführungsrecht
+     --> Schadensbegrenzung bei Abstürzen.
+         Wenn ein Benutzerprogramm gegen die Rechte verstößt, entsteht eine Ausnahmesituation.
+         Das Betriebssystem kann darauf reagieren und das Programm beenden.
+   - Bit: "vorhanden" (s.o.)
+
+  --> Das Betriebssystem kann Programme gegeneinander abschotten.
+      Damit wird Multitasking und Multi-User möglich.
+
+  Das o.a. Konzept zur Auslagerung von Speicher hat einen Nachteil.
+  Beispiel: Ein Programm A belegt 3/4 des Arbeitsspeichers.
+  Ein weiteres Programm B soll gestartet werden, das 1/3 des Arbeitsspeichers benötigt.
+  --> Der Kernel kann nun ein Segment auslagern, z.B. das Datensegment von Programm A.
+  Problem: Das Segment ist u.U. viel größer als der tatsächlich benötigte Zusatzspeicher.
+  Mit dieser Hardware kann man immer nur ganze Segmente auslagern.
+
+  Lösungsideen:
+   - mehrere kleinere Datensegmente
+     --> Dies muß man bei der Programmierung berücksichtigen.
+   - herunterbrechen auf Speicherzellenebene
+     --> Zusätzliche Hardware, die die Segmente weiter unterteilt: Memory Management Unit (MMU)
+
+AMD-64-Bit-Prozessoren (AMD Opteron, 2003, Intel-kompatibel):
+
+  MMU unterteilt den Speicher in Seiten von jeweils 4 kiB.
+  Das Betriebssystem entscheidet über die Zuordnung zwischen logischen
+  und physikalischen Speicheradressen - einschließlich Auslagerungsspeicher.
+
+  Dieser Mechanismus greift erst _nach_ den Segmenten.
+  Dies bedeutet für die Interpretation eines Zeigers:
+   - Ein Zeiger enthält eine Zahl, die Speicheradresse (Offset).
+   - Das Programm kennt das ihm zugeordnete Segment.
+     Segment und Offset definieren gemeinsam eine logische Speicheradresse.
+   - Die MMU ordnet diese logische Speicheradresse einer physikalischen zu,
+     die auch ausgelagert sein darf.
+
+  Dadurch wird möglich:
+   - Gemeinsamer Speicher mehrerer Programme (Shared Memory).
+     Dadurch möglich: extrem schnelle Kommunikation zwischen Programmen
+   - Sicherheitslücken, z.B. Meltdown, Spectre
+
+Die Meltdown-Sicherheitslücke, 16.05.2022, 12:28:15
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Situation: Ein Programm will Speicher auslesen, für den es keine Leseberechtigung hat,
+z.B. Speicher des Kernels.
+
+Vorgehensweise: siehe https://de.wikipedia.org/wiki/Meltdown_(Sicherheitsl%C3%BCcke)
+
+Wir arbeiten mit einem Riesen-Array:
+
+  #define VIELE 0xffffffffffffffff  // größtmögliche 64-Bit-Zahl
+
+  typedef uint8_t page[4096];  // Datentyp: Array von 4096 Bytes
+
+  page A[VIELE];  // Riesen-Array. Jedes einzelne Element ist 4096 Bytes groß,
+                  // und es sind VIELE Elemente.
+
+  Bei Programmstart wird das Riesen-Array nicht sofort im physikalischen Speicher angelegt.
+  Erst dann, wenn das Programm darauf zugreift, reserviert die MMU tatsächlich physikalischen Speicher.
+
+  Schritt 1: Ein "Sender"-Thread greift mit einem "verbotenen" Index auf das Array zu und stürzt ab.
+
+  Schritt 2: Ein "Empfänger"-Thread geht das Array durch
+             und prüft, bei welchem Index der Zugriff ungewöhnlich schnell erfolgt
+             (weil darauf vorher schon einmal zugegriffen wurde).
+
+"Sender"-Thread:
+
+ - Greife "einfach so" auf die Speicherzelle zu.
+   Dies bewirkt einen Absturz (Prozessor-Ausnahme; Betriebssystem beendet Programm)
+ - Danach (nach dem Absturz!) multiplizieren wir den gelesenen Wert mit 4096
+   (entsprechend der Größe einer Speicherseite, 4 kiB)
+ - Das Ergebnis benutzen wir als Index für ein Array,
+   das für den Hauptspeicher viel zu groß ist.
+ - Wäre das Programm nicht bereits abgestürzt, würde nun der Prozessor versuchen,
+   auf diese Stelle im Array zuzugreifen. Zu diesem Zweck macht er die entsprechende
+   Speicherseite zugänglich.
+
+"Empfänger"-Thread:
+
+ - Warte, bis der Sender-Thread fertig ist.
+ - Danach greife auf das Riesen-Array zu.
+ - Dort, wo die Speicher-Seite bereits zugänglich gemacht wurde, ist der Zugriff schneller.
+   Mit Hilfe einer Zeitmessung kann der Empfänger-Thread daraus schließen,
+   auf welche Speicher-Seite der Sender-Thread zuzugreifen versucht hat.
+
+Wieso funktioniert dies, wenn doch der Sender-Thread bereits vorher abgestürzt ist?
+
+ - Vorauslesen des Prozessors zur Erhöhung der Effizienz ("Instruction Pipeline").
+   Bis der Prozessor den Absturz erkennt, hat er bereits das Riesen-Array für
+   den Speicherzugriff vorbereitet.
+
+--> Hardware-Sicherheitsloch
+
+Gegenmaßnahme: KPTI (siehe: https://de.wikipedia.org/wiki/Kernel_page-table_isolation)
+ - Vorab: Kernel Address Space Layout Randomization (KASLR):
+   Die Segmente, die das Programm zugeteilt bekommt, sind jedesmal zufällig
+   und damit nicht vorhersagbar.
+ - Vorgänger: Kernel Address Isolation to have Side-channels Efficiently Removed (KAISER)
+ - Kernel Page Table Isolation (KPTI)
+   Illustration: https://en.wikipedia.org/wiki/Kernel_page-table_isolation#/media/File:Kernel_page-table_isolation.svg
+   Page Table = Seitentabelle
+              = Tabelle, die einen Zeiger (auf logischen Speicher)
+                auf eine physikalische Speicheradresse abbildet
+   
+   Das Programm arbeitet nur mit Zeigern.
+   Der Kernel kann auch die Tabelle(n) beeinflussen.
+
+   Es ist insbesondere möglich, dieselbe physikalische Speicheradresse
+   unter verschiedenen logischen Speicheradressen anzusprechen.
+
+   KPTI: Verwende verschiedene Seitentabellen im Kernel-Modus und im User-Modus.
+
+   Meltdown-Code:
+    - Sender und Empfänger arbeiten im User-Modus
+      und wollen die (logische) Speicherzelle Nr. rcx auslesen.
+    - Da der Kernel eine eigene Seitentabelle verwendet,
+      ist nicht klar, logische Speiherzelle im Kernel dafür steht
+      (oder umgekehrt:  ..., welche Bedeutung diese Speicherzelle
+      im Kernel hat).
+   --> Zeiger im Kernel und im Benutzerprogramm haben völlig unterschiedliche Bedeutungen.
+       Man weiß gar nicht mehr, welche Speicherzelle man da eigentlich ausliest.
+
+Ein Nachtrag zu SPECTRE/Meltdown: Mit dem Skript unter
+https://github.com/speed47/spectre-meltdown-checker/
+(oder gleichnamiges Debianpaket aus einer möglichst aktuellen Distribution)
+können Sie Ihr Linux-System gegen entsprechende Sicherheitslücken überprüfen.
+
+Ähnliches Konzept:
+  Ausnutzen von Pufferüberläufen und Maßnahmen dagegen
+  --> Nächste Woche
+
+Gemeinsamer Speicher (Shared Memory), 16.05.2022, 14:10:56
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+shm-1: Ein Programm kann einen gemeinsamen Speicherbereich wie eine Datei öffnen.
+       Es gibt einen ("Datei-") Namen und einen Modus (rwxrwxrwx) wie bei Dateien.
+
+       Siehe: man shm_open
+
+shm-2: Man muß die "Datei" auch schließen, sonst verliert man die Daten.
+
+shm-3: Die Vorgehensweise mit SHM als "Datei" ist nahezu identisch dazu,
+       daß ein Programm die Daten in eine Datei schreibt
+       und ein anderes sie daraus wieder liest.
+
+shm-4: Alternative: Ich kann die "Datei" in einen Zeiger umwandeln
+       und damit direkt auf den gemeinsamen Speicherbereich zugreifen.
+
+shm-5: Umgekehrt kann man übrigens auch eine echte(!) Datei in einen Zeiger umwandeln
+       und auf die Datei zugreifen, als wäre sie ein Speicherbereich.
+
+shm-7: Wo liegt der Speicherbereich? --> Das wissen wir nicht.
+       Jedes Programm, das auf den Speicherbereich zugreift, bekommt einen anderen(!)
+       Zeiger, obwohl alle diese Zeiger auf denselben physikalischen Speicherbereich zeigen.
+
+shm-8: Nach Gebrauch sollte man den gemeinsamen Speicherbereich wieder freigeben
+       (analog zum Löschen einer temporären Datei).
+
+Ergänzung: Mit der Funktion mmap() kann man auch eine Pseudo-Datei im /proc-Verzeichnis
+           öffnen (/proc/kcore?), über die der Kernel den gesamten Speicher als Datei
+           zur Verfügung stellt. (Diese Datei ist nur für den Administrator freigegeben.)
+           --> Man kann mit einem Zeiger auf beliebige Speicherzellen zugreifen.
+           Anwendung: GPIOs auf Einplatinen-Computern ansprechen.
diff --git a/20220516/buffer-overflow-01.c b/20220516/buffer-overflow-01.c
new file mode 100644
index 0000000000000000000000000000000000000000..589cc0a64f89e08c6a7cf5b53f0c99d8ca932962
--- /dev/null
+++ b/20220516/buffer-overflow-01.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int main (void)
+{
+  char buffer[20];
+  gets (buffer);
+  printf ("Guten Tag, %s!\n", buffer);
+  return 0;
+}
diff --git a/20220516/buffer-overflow-01.txt b/20220516/buffer-overflow-01.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9277da31e7a3e8b5f7f0ccb369f6eee47efde650
--- /dev/null
+++ b/20220516/buffer-overflow-01.txt
@@ -0,0 +1,28 @@
+#include <stdio.h>
+
+int main (void)
+{
+  char buffer[20];
+  gets (buffer);
+  printf ("Guten Tag, %s!\n", buffer);
+  return 0;
+}
+cassini/home/peter/bo/2022ss/bs/20220516> gcc -Wall -O buffer-overflow-01.c -o buffer-overflow-01
+buffer-overflow-01.c: In function ‘main’:
+buffer-overflow-01.c:6:3: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
+   gets (buffer);
+   ^~~~
+   fgets
+/usr/bin/ld: /tmp/cc8eISnL.o: in function `main':
+buffer-overflow-01.c:(.text+0x11): Warnung:the `gets' function is dangerous and should not be used.
+cassini/home/peter/bo/2022ss/bs/20220516> ./buffer-overflow-01
+Peter
+Guten Tag, Peter!
+cassini/home/peter/bo/2022ss/bs/20220516> ./buffer-overflow-01
+Prof. Dr. rer. nat. Peter Gerwinski
+Guten Tag, Prof. Dr. rer. nat. Peter Gerwinski!
+cassini/home/peter/bo/2022ss/bs/20220516> ./buffer-overflow-01
+Prof. Dr. rer. nat. Dipl.-Phys. Peter Gerwinski
+Guten Tag, Prof. Dr. rer. nat. Dipl.-Phys. Peter Gerwinski!
+Speicherzugriffsfehler
+cassini/home/peter/bo/2022ss/bs/20220516>
diff --git a/20220516/hello-01.c b/20220516/hello-01.c
new file mode 100644
index 0000000000000000000000000000000000000000..b3201f333349fb959daf5c8216ed5f078727b41f
--- /dev/null
+++ b/20220516/hello-01.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int main (void)
+{
+  char *hello = "Hello!";
+  printf ("%s\n", hello);
+  return 0;
+}
diff --git a/20220516/hello-02.c b/20220516/hello-02.c
new file mode 100644
index 0000000000000000000000000000000000000000..23686a622d7a75ef5e08af6bba8dbb9ecfca503d
--- /dev/null
+++ b/20220516/hello-02.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int main (void)
+{
+  char *hello = "Hello!";
+  hello[1] = 'a';
+  printf ("%s\n", hello);
+  return 0;
+}
diff --git a/20220516/hello-02.s b/20220516/hello-02.s
new file mode 100644
index 0000000000000000000000000000000000000000..e396f2a4ef344f7621d2046e5178084921a40b57
--- /dev/null
+++ b/20220516/hello-02.s
@@ -0,0 +1,25 @@
+	.file	"hello-02.c"
+	.text
+	.section	.rodata.str1.1,"aMS",@progbits,1
+.LC0:
+	.string	"Hello!"
+	.text
+	.globl	main
+	.type	main, @function
+main:
+.LFB11:
+	.cfi_startproc
+	subq	$8, %rsp
+	.cfi_def_cfa_offset 16
+	movb	$97, 1+.LC0(%rip)
+	leaq	.LC0(%rip), %rdi
+	call	puts@PLT
+	movl	$0, %eax
+	addq	$8, %rsp
+	.cfi_def_cfa_offset 8
+	ret
+	.cfi_endproc
+.LFE11:
+	.size	main, .-main
+	.ident	"GCC: (Debian 8.3.0-6) 8.3.0"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/20220516/shm-1a.c b/20220516/shm-1a.c
new file mode 100644
index 0000000000000000000000000000000000000000..c404db3bdb22a6b0a0a1e30b47b4b2de0a048f12
--- /dev/null
+++ b/20220516/shm-1a.c
@@ -0,0 +1,10 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int main (void)
+{
+  int shm = shm_open ("test", O_RDWR, 0666);
+  write (shm, "Hello, world!", 13);
+  return 0;
+}
diff --git a/20220516/shm-1b.c b/20220516/shm-1b.c
new file mode 100644
index 0000000000000000000000000000000000000000..de7774f79a26406bf5032f8d9a4fa543e35963fe
--- /dev/null
+++ b/20220516/shm-1b.c
@@ -0,0 +1,13 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  char buffer[42];
+  int shm = shm_open ("test", O_RDONLY, 0444);
+  read (shm, buffer, 42);
+  printf ("%s\n", buffer);
+  return 0;
+}
diff --git a/20220516/shm-1c.c b/20220516/shm-1c.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff6363eddfa2b6d26ae5c390f96306702afd60f8
--- /dev/null
+++ b/20220516/shm-1c.c
@@ -0,0 +1,14 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  char buffer[42];
+  int shm = shm_open ("test", O_RDONLY, 0444);
+  lseek (shm, 0, SEEK_SET);
+  read (shm, buffer, 42);
+  printf ("%s\n", buffer);
+  return 0;
+}
diff --git a/20220516/shm-2a.c b/20220516/shm-2a.c
new file mode 100644
index 0000000000000000000000000000000000000000..8853ecaed14074e136a764fbdb868d5fe7a4baf3
--- /dev/null
+++ b/20220516/shm-2a.c
@@ -0,0 +1,11 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+int main (void)
+{
+  int shm = shm_open ("test", O_CREAT | O_RDWR, 0666);
+  write (shm, "Hello, world!", 14);
+  close (shm);
+  return 0;
+}
diff --git a/20220516/shm-2b.c b/20220516/shm-2b.c
new file mode 100644
index 0000000000000000000000000000000000000000..92ef091a9f00a93ed834071bd425b5b60238c3ee
--- /dev/null
+++ b/20220516/shm-2b.c
@@ -0,0 +1,14 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  char buffer[42];
+  int shm = shm_open ("test", O_RDONLY, 0444);
+  read (shm, buffer, 42);
+  close (shm);
+  printf ("%s\n", buffer);
+  return 0;
+}
diff --git a/20220516/shm-3a.c b/20220516/shm-3a.c
new file mode 100644
index 0000000000000000000000000000000000000000..b5273ec483618b33585ff78f70f419bdff149950
--- /dev/null
+++ b/20220516/shm-3a.c
@@ -0,0 +1,14 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  int file = open ("test.txt", O_CREAT | O_RDWR, 0666);
+  printf ("file = %d\n", file);
+  lseek (file, 0, SEEK_SET);
+  write (file, "Hello, world!", 14);
+  close (file);
+  return 0;
+}
diff --git a/20220516/shm-3b.c b/20220516/shm-3b.c
new file mode 100644
index 0000000000000000000000000000000000000000..21f2d5d32d075a33bd94abeb9b69495d58b8c8a5
--- /dev/null
+++ b/20220516/shm-3b.c
@@ -0,0 +1,15 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  char buffer[42];
+  int file = open ("test.txt", O_RDONLY, 0444);
+  lseek (file, 0, SEEK_SET);
+  read (file, buffer, 42);
+  close (file);
+  printf ("%s\n", buffer);
+  return 0;
+}
diff --git a/20220516/shm-4a.c b/20220516/shm-4a.c
new file mode 100644
index 0000000000000000000000000000000000000000..00ddb6790a669f3040dd7439c98c30d01227662d
--- /dev/null
+++ b/20220516/shm-4a.c
@@ -0,0 +1,14 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+int main (void)
+{
+  int shm = shm_open ("test", O_CREAT | O_RDWR, 0666);
+  char *buffer = mmap (NULL, 42, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
+  strcpy (buffer, "Hello, world!");
+  munmap (buffer, 42);
+  close (shm);
+  return 0;
+}
diff --git a/20220516/shm-4b.c b/20220516/shm-4b.c
new file mode 100644
index 0000000000000000000000000000000000000000..34c4b6ae3bebb451979307c61f3cfe66c5477f87
--- /dev/null
+++ b/20220516/shm-4b.c
@@ -0,0 +1,14 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  int shm = shm_open ("test", O_RDONLY, 0444);
+  char *buffer = mmap (NULL, 42, PROT_READ, MAP_SHARED, shm, 0);
+  printf ("%s\n", buffer);
+  munmap (buffer, 42);
+  close (shm);
+  return 0;
+}
diff --git a/20220516/shm-5a.c b/20220516/shm-5a.c
new file mode 100644
index 0000000000000000000000000000000000000000..8acc3dde82d8d7f7c4fd77714a3f5f65b7aa2b96
--- /dev/null
+++ b/20220516/shm-5a.c
@@ -0,0 +1,14 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+int main (void)
+{
+  int file = open ("test.txt", O_CREAT | O_RDWR, 0666);
+  char *buffer = mmap (NULL, 42, PROT_READ | PROT_WRITE, MAP_SHARED, file, 0);
+  strcpy (buffer, "Hello, world!");
+  munmap (buffer, 42);
+  close (file);
+  return 0;
+}
diff --git a/20220516/shm-5b.c b/20220516/shm-5b.c
new file mode 100644
index 0000000000000000000000000000000000000000..c31ba9b27a39f587474632b0442cbc33d20206eb
--- /dev/null
+++ b/20220516/shm-5b.c
@@ -0,0 +1,14 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  int file = open ("test.txt", O_RDONLY, 0444);
+  char *buffer = mmap (NULL, 42, PROT_READ, MAP_SHARED, file, 0);
+  printf ("%s\n", buffer);
+  munmap (buffer, 42);
+  close (file);
+  return 0;
+}
diff --git a/20220516/shm-6a.c b/20220516/shm-6a.c
new file mode 100644
index 0000000000000000000000000000000000000000..45e883c1f746de42bf8b2cfc0bcebb61e9c862e2
--- /dev/null
+++ b/20220516/shm-6a.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+int main (void)
+{
+  int file = open ("test.txt", O_CREAT | O_RDWR, 0666);
+  fprintf (stderr, "0\n");
+  char *buffer = mmap (NULL, 42, PROT_READ | PROT_WRITE, MAP_SHARED, file, 0);
+  fprintf (stderr, "1\n");
+  strcpy (buffer, "Hello, world!");
+  fprintf (stderr, "2\n");
+  munmap (buffer, 42);
+  fprintf (stderr, "3\n");
+  close (file);
+  return 0;
+}
diff --git a/20220516/shm-6c.c b/20220516/shm-6c.c
new file mode 100644
index 0000000000000000000000000000000000000000..c4c537612a4d24d1b7bf20bb8c3f53a30c0a3322
--- /dev/null
+++ b/20220516/shm-6c.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+int main (void)
+{
+  int file = open ("test.txt", O_CREAT | O_RDWR, 0666);
+  fprintf (stderr, "0\n");
+  char *buffer = mmap (NULL, 42, PROT_READ | PROT_WRITE, MAP_SHARED, file, 0);
+  fprintf (stderr, "1\n");
+  strcpy (buffer, "Dies ist ein weiterer Test.");
+  fprintf (stderr, "2\n");
+  munmap (buffer, 42);
+  fprintf (stderr, "3\n");
+  close (file);
+  return 0;
+}
diff --git a/20220516/shm-7.txt b/20220516/shm-7.txt
new file mode 100644
index 0000000000000000000000000000000000000000..42250e229b66f3e27fa2fcf3bd300f5f96795230
--- /dev/null
+++ b/20220516/shm-7.txt
@@ -0,0 +1,51 @@
+cassini/home/peter/bo/2022ss/bs/20220516> cat shm-7a.c
+#include <stdio.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+int main (void)
+{
+  int shm = shm_open ("test", O_CREAT | O_RDWR, 0666);
+  char *buffer = mmap (NULL, 42, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
+  printf ("%016zx\n", buffer);
+  strcpy (buffer, "Hello, world!");
+  munmap (buffer, 42);
+  close (shm);
+  return 0;
+}
+cassini/home/peter/bo/2022ss/bs/20220516> gcc -Wall -O shm-7a.c -lrt -o shm-7a
+shm-7a.c: In function ‘main’:
+shm-7a.c:11:17: warning: format ‘%zx’ expects argument of type ‘size_t’, but argument 2 has type ‘char *’ [-Wformat=]
+   printf ("%016zx\n", buffer);
+            ~~~~~^     ~~~~~~
+            %016s
+cassini/home/peter/bo/2022ss/bs/20220516> ./shm-7a
+00007f40c3ceb000
+cassini/home/peter/bo/2022ss/bs/20220516> cat shm-7b.c
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  int shm = shm_open ("test", O_RDONLY, 0444);
+  char *buffer = mmap (NULL, 42, PROT_READ, MAP_SHARED, shm, 0);
+  printf ("%016zx\n", buffer);
+  printf ("%s\n", buffer);
+  munmap (buffer, 42);
+  close (shm);
+  return 0;
+}
+cassini/home/peter/bo/2022ss/bs/20220516> gcc -Wall -O shm-7b.c -lrt -o shm-7b
+shm-7b.c: In function ‘main’:
+shm-7b.c:10:17: warning: format ‘%zx’ expects argument of type ‘size_t’, but argument 2 has type ‘char *’ [-Wformat=]
+   printf ("%016zx\n", buffer);
+            ~~~~~^     ~~~~~~
+            %016s
+cassini/home/peter/bo/2022ss/bs/20220516> ./shm-7b
+00007fd7e2c36000
+Hello, world!
+cassini/home/peter/bo/2022ss/bs/20220516>
diff --git a/20220516/shm-7a.c b/20220516/shm-7a.c
new file mode 100644
index 0000000000000000000000000000000000000000..4641337ca7d979440d493311193e618d713f1f27
--- /dev/null
+++ b/20220516/shm-7a.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+int main (void)
+{
+  int shm = shm_open ("test", O_CREAT | O_RDWR, 0666);
+  char *buffer = mmap (NULL, 42, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
+  printf ("%016zx\n", buffer);
+  strcpy (buffer, "Hello, world!");
+  munmap (buffer, 42);
+  close (shm);
+  return 0;
+}
diff --git a/20220516/shm-7b.c b/20220516/shm-7b.c
new file mode 100644
index 0000000000000000000000000000000000000000..e39d524762cc641d3c019cc16a7193424b3bca43
--- /dev/null
+++ b/20220516/shm-7b.c
@@ -0,0 +1,15 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int main (void)
+{
+  int shm = shm_open ("test", O_RDONLY, 0444);
+  char *buffer = mmap (NULL, 42, PROT_READ, MAP_SHARED, shm, 0);
+  printf ("%016zx\n", buffer);
+  printf ("%s\n", buffer);
+  munmap (buffer, 42);
+  close (shm);
+  return 0;
+}
diff --git a/20220516/shm-8.c b/20220516/shm-8.c
new file mode 100644
index 0000000000000000000000000000000000000000..f2397311753bbcdc9e747804c3c0ccf04087533f
--- /dev/null
+++ b/20220516/shm-8.c
@@ -0,0 +1,7 @@
+#include <sys/mman.h>
+
+int main (void)
+{
+  shm_unlink ("test");
+  return 0;
+}
diff --git a/20220516/test.txt b/20220516/test.txt
new file mode 100644
index 0000000000000000000000000000000000000000..14220de2cc6ba7ad7258bcab5c4c37820ca3b59c
Binary files /dev/null and b/20220516/test.txt differ