Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add example program of a pipe "Nein, doch, oh!" #127

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 148 additions & 4 deletions RES-GUENTHER/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ date: "Semester 5"
keywords: [Systemprogrammierung, Verteilte Systeme, RES, DHGE, Semester 5]
---------->

Systemprogrammierung / Verteilte Systeme
========================================
# Systemprogrammierung / Verteilte Systeme

<!-- md2apkg ignore-card -->

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

**Inhaltsverzeichnis**

- [Klausur](#klausur)
Expand Down Expand Up @@ -148,14 +148,15 @@ int main()

#### Pipes

- *Rohre* zwischen Prozessen, in denen Nachrichten transportiert werden können
- _Rohre_ zwischen Prozessen, in denen Nachrichten transportiert werden können
- nur in eine Richtung
- Pipes können nur zwischen Prozessen mit gemeinsamen Vorfahren eingerichtet werden
- Ablauf:
- Vaterprozess erzeugt Pipe
- Vaterprozess erzeugt Sohnprozess mit `fork()`
- Sohnprozess erbt Pipe
- Programmierung:

- Inkludierung von `sys/unistd.h`
- `int pipe(int fd[2])`
- `fd[0]` zum Lesen
Expand All @@ -164,8 +165,151 @@ int main()
- wurden alle Leseseiten einer Pipe bereits gelesen, liefert `read()` EOF
- Schreib-Operation: `write()`
- Schließ-Operation: `close()`
<details>
<summary>Beispielprogramm "Nein, doch, oh!"</summary>

```c++
/// \brief This program creates two pipes and forks a child process to print out "Nein! Doch! Oh!".
/// \details The PARENT process uses the pipe1 to read the messages to the child process and uses the pipe2 to write the messages from the child process.
/// The CHILD process uses the pipe1 to write the messages from the parent process and uses the pipe2 to read the messages to the parent process.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>

static const int FORK_CHILD_PID = 0;
static const int FORK_ERROR_PID = -1;

static const int PIPE_ERROR = -1;
static const int PIPE_SIZE = 2;
static const int PIPE_READ_INDEX = 0;
static const int PIPE_WRITE_INDEX = 1;

static const char *PARENT_MESSAGE_1 = "Nein!\n";
static const char *PARENT_MESSAGE_2 = "Oh!\n";
static const char *CHILD_MESSAGE_1 = "Doch!\n";

void createPipe(int pipeFileDescriptor[]);
void sendPipeMessage(int pipeFileDescriptor[], const char *message);
void receivePipeMessage(int pipeFileDescriptor[], char *message);

/// @brief Creates a pipe and checks if it was created successfully.
/// @param pipeFileDescriptor The pipe file descriptor.
void createPipe(int pipeFileDescriptor[])
{
if (pipe(pipeFileDescriptor) == PIPE_ERROR)
{
perror("Pipe creation failed");
exit(EXIT_FAILURE);
}
}

/// @brief Sends a message through a pipe.
/// @param pipeFileDescriptor The pipe file descriptor. Assumed that the write end (index = 1) is open.
/// @param message The message to send.
void sendPipeMessage(int pipeFileDescriptor[], const char *message)
{
const ssize_t bytesWritten = write(pipeFileDescriptor[PIPE_WRITE_INDEX], message, strlen(message));
if (bytesWritten == -1)
{
perror("Write failed");
exit(EXIT_FAILURE);
}
}

/// @brief Receives a message through a pipe.
/// @param pipeFileDescriptor The pipe file descriptor. Assumed that the read end (index = 0) is open.
/// @param message The message to receive.
void receivePipeMessage(int pipeFileDescriptor[], char *message)
{
const ssize_t bytesRead = read(pipeFileDescriptor[PIPE_READ_INDEX], message, strlen(message));
if (bytesRead == -1)
{
perror("Read failed");
exit(EXIT_FAILURE);
}

// Null-terminate the received message
message[bytesRead] = '\0';
}

int main()
{
int pipeFileDescriptor1[PIPE_SIZE];
int pipeFileDescriptor2[PIPE_SIZE];

createPipe(pipeFileDescriptor1);
createPipe(pipeFileDescriptor2);

const pid_t childPid = fork();

if (childPid == FORK_ERROR_PID)
{
perror("Fork failed");
exit(EXIT_FAILURE);
}
// in a child process
else if (childPid == FORK_CHILD_PID)
{
printf("Bin das Kind: %d\n", getpid());

// Close unused read end
close(pipeFileDescriptor1[PIPE_READ_INDEX]);
// Close unused write end
close(pipeFileDescriptor2[PIPE_WRITE_INDEX]);

char incoming_message[strlen(PARENT_MESSAGE_1)];
receivePipeMessage(pipeFileDescriptor2, incoming_message);
printf("Vom Vater: %s", incoming_message);

sendPipeMessage(pipeFileDescriptor1, CHILD_MESSAGE_1);

char incoming_message2[strlen(PARENT_MESSAGE_2)];
receivePipeMessage(pipeFileDescriptor2, incoming_message2);
printf("Vom Vater: %s", incoming_message2);

// Close write end
close(pipeFileDescriptor1[PIPE_WRITE_INDEX]);
// Close read end
close(pipeFileDescriptor2[PIPE_READ_INDEX]);
}
// in a parent process
else if (childPid > FORK_CHILD_PID)
{
printf("Bin der Vater: %d\n", getpid());

// Close unused write end
close(pipeFileDescriptor1[PIPE_WRITE_INDEX]);
// Close unused read end
close(pipeFileDescriptor2[PIPE_READ_INDEX]);

sendPipeMessage(pipeFileDescriptor2, PARENT_MESSAGE_1);

char incoming_message[strlen(CHILD_MESSAGE_1)];
receivePipeMessage(pipeFileDescriptor1, incoming_message);
printf("Vom Kind: %s", incoming_message);

sendPipeMessage(pipeFileDescriptor2, PARENT_MESSAGE_2);

// Close read end
close(pipeFileDescriptor1[PIPE_READ_INDEX]);
// Close write end
close(pipeFileDescriptor2[PIPE_WRITE_INDEX]);
}
else
{
perror("Fork failed");
exit(EXIT_FAILURE);
}

return EXIT_SUCCESS;
}
```
</details>

#### Sockets

- IPC auf lokalem Rechner (Unix-Domäne) oder über das Internet (Internet-Domäne)
- Ein Port ist eine Spezifikation zur Addressierung eines Prozesses auf einem Host
- Ein Port ist eine Spezifikation zur Addressierung eines Prozesses auf einem Host