initial commit

This commit is contained in:
Daniel Meiburg 2024-12-09 09:43:14 +01:00
commit 8b3abe2dde
Signed by: dm
GPG Key ID: E5827ECFFE0AA4F2
30 changed files with 1864 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*
!*.*
!*/
*.ova
*.iso
*.pdf

36
ex01/aufgabe2.c Normal file
View File

@ -0,0 +1,36 @@
//////////////////////////////////////////////////////////////////////////////
// Course: Real Time Systems
// Lecturer: Dr.-Ing. Frank Golatowski
// Exercise instructor: M.Sc. Michael Rethfeldt
// Exercise: 1
// Task: 2
// Name: aufgabe2.c
// Description: ?
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
int status;
pid_t fork_pid;
if ( (fork_pid=fork() ) == 0 )
{
printf("* I am the son. *\n");
exit(3);
}
else if (fork_pid == -1)
{
printf("fork() failed!\n");
exit(2);
}
wait(&status); // wait for termination of son process
// status: hexa decimal output from son process
// (status>>8) & 0xff: second (higher byte) of the status
// status & 0xff: first (lower byte) of the status
printf("wait status: 0x%x | 0x%x | 0x%x |\n", status, (status>>8) & 0xff, status & 0xff);
return 0;
}

6
ex01/hello_world.c Normal file
View File

@ -0,0 +1,6 @@
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}

24
ex01/manual_termination.c Normal file
View File

@ -0,0 +1,24 @@
#include <stdio.h>
#include <unistd.h> // fork, sleep
#include <stdlib.h> // exit
#include <sys/wait.h> // wait
int main(){
int status;
int pid;
if ((pid = fork()) == 0) {
printf("I'm the son and going to sleep for 30s.\n");
sleep(30);
exit(3);
}
else if (pid == -1) {
printf("fork() failed");
exit(2);
}
wait(&status);
printf("wait status 0x%x | 0x%x | 0x%x\n", status, (status>>8) & 0xff, status & 0xff);
return 0;
}

39
ex01/signal_termination.c Normal file
View File

@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
int main(void)
{
int status;
pid_t fork_pid;
if ( (fork_pid = fork()) == 0 )
{
printf("* I am the son. About to terminate by signal... *\n");
// Send SIGKILL to this process (self-termination with a signal)
raise(SIGKILL); // Alternatively, try SIGTERM, SIGSEGV, etc.
}
else if (fork_pid == -1)
{
printf("fork() failed!\n");
exit(2);
}
wait(&status); // wait for termination of child process
// status: full status returned by wait()
// (status >> 8) & 0xff: higher byte (exit code in normal exit)
// status & 0xff: lower byte (termination signal or additional info)
printf("wait status: 0x%x | Exit code: 0x%x | Signal: 0x%x |\n",
status, (status >> 8) & 0xff, status & 0x7f);
// Check if child terminated by signal
if (WIFSIGNALED(status))
{
printf("Child was terminated by signal %d\n", WTERMSIG(status));
}
return 0;
}

View File

@ -0,0 +1,40 @@
// Create a program that creates a child process using fork.
// The parent and child processes should count from 0 to N, printing every STEP.
// N and step are supplied via command line arguments.
#include <stdio.h>
#include <stdlib.h> // exit
#include <unistd.h> // fork, sleep
#include <sys/wait.h> // wait
int count(char *who, int n, int step){
// count from 0 to print every step
for (int i = 0; i <= n; i++){
if (i % step == 0)
printf("%s:\t%d\n", who, i);
}
return 0;
}
int main(int argc, char *argv[]){
if (argc != 3){
printf("Usage: %s N STEP\n", argv[0]);
exit(1);
}
int N = atoi(argv[1]);
int STEP = atoi(argv[2]);
int status;
int pid;
if ((pid = fork()) == 0){
count("child", N, STEP);
exit(0);
}
else if (pid == -1){
printf("fork failed.\n");
exit(2);
}
count("parent", N, STEP);
return 0;
}

View File

@ -0,0 +1,39 @@
// This program creates a fork and uses execl to run the ls command
// in the child process. The parent process waits for the child to
// finish and then prints a message containing the child's exit status.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define LS "/run/current-system/sw/bin/ls"
#define PATH "/home/dm"
int main() {
pid_t pid;
int status;
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) {
// Child process
execl(LS, "ls", "-lasi", PATH, NULL);
// this line will only be reached if execl fails, meaning that it
// will not influence the status
perror("execl");
exit(3);
}
// Parent process
wait(&status);
printf("exit status: 0x%04x\n", status);
printf("Child exited with status %d\n", WEXITSTATUS(status));
return 0;
}

View File

@ -0,0 +1,44 @@
// This program creates a fork and uses execl to run the ls command
// in the child process. The parent process waits for the child to
// finish and then prints a message containing the child's exit status.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define LS "/run/current-system/sw/bin/ls"
#define PATH "/home/dm"
int main() {
pid_t pid;
int status;
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) {
// Child process
printf("child: PID = %d, PPID = %d, GID = %d, PGID = %d\n",
getpid(), getppid(), getgid(), getpgid(getpid()));
execl(LS, "ls", "-lasi", PATH, NULL);
// this line will only be reached if execl fails, meaning that it
// will not influence the status
perror("execl");
exit(3);
}
printf("parent: PID = %d, PPID = %d, GID = %d, PGID = %d\n",
getpid(), getppid(), getgid(), getpgid(getpid()));
// Parent process
wait(&status);
printf("exit status: 0x%04x\n", status);
printf("Child exited with status %d\n", WEXITSTATUS(status));
return 0;
}

20
ex01/zusatz1.c Normal file
View File

@ -0,0 +1,20 @@
//////////////////////////////////////////////////////////////////////////////
// Course: Real Time Systems
// Lecturer: Dr.-Ing. Frank Golatowski
// Exercise instructor: M.Sc. Michael Rethfeldt
// Exercise: 1
// Task: zusatz1
// Name: zusatz1.c
// Description: ?
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
fork();
fork();
printf("test\n");
}

28
ex01/zusatz2.c Normal file
View File

@ -0,0 +1,28 @@
//////////////////////////////////////////////////////////////////////////////
// Course: Real Time Systems
// Lecturer: Dr.-Ing. Frank Golatowski
// Exercise instructor: M.Sc. Michael Rethfeldt
// Exercise: 1
// Task: zusatz2
// Name: zusatz2.c
// Description: ?
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
switch ( fork() ) {
case 0: printf("Son created\n");
break;
default: switch ( fork() ) {
case 0: printf("Son created\n");
break;
default: printf("Father\n");
break;
}
break;
}
}

19
ex02/aufgabe1_sohn.c Normal file
View File

@ -0,0 +1,19 @@
//////////////////////////////////////////////////////////////////////////////
// Course: Real Time Systems
// Lecturer: Dr.-Ing. Frank Golatowski
// Exercise instructor: M.Sc. Michael Rethfeldt
// Exercise: 2
// Task: 1
// Name: aufgabe1_sohn.c
// Description: Son process
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
printf("I am the son.\n");
return 0;
}

30
ex02/aufgabe1_vater.c Normal file
View File

@ -0,0 +1,30 @@
//////////////////////////////////////////////////////////////////////////////
// Course: Real Time Systems
// Lecturer: Dr.-Ing. Frank Golatowski
// Exercise instructor: M.Sc. Michael Rethfeldt
// Exercise: 2
// Task: 1
// Name: aufgabe1_vater.c
// Description: Father process executes an external son process
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{ int status;
pid_t fork_pid;
if ( (fork_pid=fork() ) == 0 )
{ execl("./son", "son", NULL);
printf("execl() failed!\n");
exit(3);
}
else if (fork_pid == -1)
{ printf("fork() failed!\n");
exit(2);
}
wait(&status); // wait for termination of son
printf("wait status: 0x%x | 0x%x | 0x%x |\n", status, (status>>8) & 0xff, status & 0xff);
return 0;
}

30
ex02/aufgabe2.c Normal file
View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
int var = 0;
printf("PID(Father)=%d, PPID=%d, var=%d\n", getpid(), getppid(), var);
if ( fork() == -1 )
{
fprintf( stderr, "fork() failed!\n" );
}
else
{
var++;
printf("PID=%d, PPID=%d, var=%d\n", getpid(), getppid(), var);
if ( fork() == -1 )
{
fprintf( stderr, "Error at 2nd fork()!\n");
}
else
{
var++;
printf("PID=%d, PPID=%d, var=%d\n", getpid(), getppid(), var);
}
}
return 0;
}

44
ex02/ex03_multiple_sons.c Normal file
View File

@ -0,0 +1,44 @@
// create a number N of child processes specified via commandline argument
// each child sleeps for a random time between 1 and 5 seconds
// each child prints its PID and the time it slept
// the parent waits for all children to finish and then exits
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <number of children>\n", argv[0]);
return 1;
}
int n = atoi(argv[1]);
for (int i = 0; i < n; i++) {
pid_t pid = fork();
if (pid < 0) {
perror("fork");
return 1;
}
if (pid == 0) {
// child
srand(getpid());
int sleep_time = 1 + rand() % 5;
printf("Child %d with PID %d will sleep for %d seconds\n", i, getpid(), sleep_time);
sleep(sleep_time);
printf("Child %d with PID %d slept for %d seconds\n", i, getpid(), sleep_time);
return 0;
}
}
// parent
for (int i = 0; i < n; i++) {
int status;
wait(&status);
}
return 0;
}

75
ex03/t01.c Normal file
View File

@ -0,0 +1,75 @@
//////////////////////////////////////////////////////////////////////////////
// Course: Real Time Systems
// Lecturer: Dr.-Ing. Frank Golatowski
// Exercise instructor: M.Sc. Michael Rethfeldt
// Exercise: 3
// Task: 1
// Name: aufgabe1.c
// Description: ?
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <ctype.h>
void hex_print(FILE *dz, char *s)
{
int fd[2];
if (pipe(fd) != 0) {
fprintf(stderr, "Error while creating pipe!\n");
exit(1);
} else {
printf("Hex print of %s\n\n",s);
switch(fork()) {
case -1:{ fprintf(stderr, "fork() failed\n");
exit(1);
}
case 0:{ int i=1;
unsigned char read_char;
close(fd[1]);
while (read(fd[0], &read_char, 1) > 0) {
printf(" %02x", read_char);
if (++i > 16) {
printf("\n");
i=1;
}
}
printf("\n");
close(fd[0]);
exit(0);
}
default:{ unsigned char c;
int status;
close(fd[0]);
while (fread(&c,1,1,dz) > 0)
write(fd[1], &c, 1);
close(fd[1]);
wait(&status);
}
}
}
}
int main(int argc, char *argv[])
{
FILE *dz;
int i;
if (argc < 2) {
fprintf(stderr, "Call: aufgabe1 <filename>\n");
exit(1);
}
for (i=1; i<argc; i++) {
if ((dz=fopen(argv[i],"rb")) == NULL ) {
fprintf(stderr,"Can't open file %s\n", argv[i]);
exit(1);
} else {
hex_print(dz,argv[i]);
fclose(dz);
}
}
}

48
ex03/t03_sig_child.c Normal file
View File

@ -0,0 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
void handle_sigint(int sig) {
// Father ignores SIGINT
printf("Father process received SIGINT, but ignoring it.\n");
}
void handle_son_termination(int status) {
if (WIFEXITED(status)) {
printf("Son terminated with exit status %d.\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("Son terminated by signal %d.\n", WTERMSIG(status));
} else {
printf("Son terminated with unknown status.\n");
}
}
int main() {
pid_t pid = fork();
if (pid == -1) {
perror("fork failed");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// Son process
signal(SIGINT, SIG_DFL); // Allow son process to be terminated by SIGINT
for (int i = 0; i < 10; ++i) {
printf("Son PID: %d\n", getpid());
sleep(1);
}
printf("Son terminating after 10 seconds.\n");
exit(0);
} else {
// Father process
signal(SIGINT, handle_sigint); // Ignore SIGINT in father
int status;
waitpid(pid, &status, 0); // Wait for son's termination
handle_son_termination(status);
}
return 0;
}

View File

@ -0,0 +1,94 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void writer_process(int fd_write, FILE *file) {
unsigned char c;
// Close the unused read end of the pipe
close(fd_write - 1); // fd[0] is read end, fd[1] is write end, so fd_write - 1 points to read end
// Write the file data byte by byte to the pipe
while (fread(&c, 1, 1, file) > 0) {
write(fd_write, &c, 1);
}
// Close the write end of the pipe after finishing
close(fd_write);
exit(0); // Exit after writing
}
void reader_process(int fd_read) {
unsigned char read_char;
int i = 1;
// Close the unused write end of the pipe
close(fd_read + 1); // fd[1] is write end, so fd_read + 1 points to write end
// Read from the pipe and print in hexadecimal format
while (read(fd_read, &read_char, 1) > 0) {
printf(" %02x", read_char);
if (++i > 16) { // Print 16 bytes per line
printf("\n");
i = 1;
}
}
printf("\n");
// Close the read end of the pipe after finishing
close(fd_read);
exit(0); // Exit after reading and printing
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
exit(1);
}
// Open the file in binary mode
FILE *file = fopen(argv[1], "rb");
if (file == NULL) {
fprintf(stderr, "Can't open file %s\n", argv[1]);
exit(1);
}
int fd[2];
if (pipe(fd) != 0) {
fprintf(stderr, "Error while creating pipe!\n");
exit(1);
}
// Fork writer process
pid_t writer_pid = fork();
if (writer_pid < 0) {
fprintf(stderr, "Failed to create writer process.\n");
exit(1);
} else if (writer_pid == 0) {
// Writer process logic
writer_process(fd[1], file);
}
// Close file in the parent after creating the writer
fclose(file);
// Fork reader process
pid_t reader_pid = fork();
if (reader_pid < 0) {
fprintf(stderr, "Failed to create reader process.\n");
exit(1);
} else if (reader_pid == 0) {
// Reader process logic
reader_process(fd[0]);
}
// In the father process: close both ends of the pipe
close(fd[0]);
close(fd[1]);
// Wait for both children to finish
waitpid(writer_pid, NULL, 0);
waitpid(reader_pid, NULL, 0);
return 0;
}

BIN
ex03/testfile.zip Normal file

Binary file not shown.

117
ex06/aufgabe1.c Normal file
View File

@ -0,0 +1,117 @@
// Compiler call: cc -o aufgabe1 aufgabe1.c -lpthread
#include <pthread.h>
#include <stdio.h>
//#include <stdlib.h>
#include <unistd.h>
int make_new_item(void);
void consume_item(char a, int count);
void* reader_function(void*);
void writer_function(void);
char buffer;
int buffer_has_item = 0;
pthread_mutex_t mutex;
void cleanup_resources() {
pthread_mutex_destroy(&mutex);
}
int main(int argc, char *argv[]){
pthread_mutexattr_t mutex_attr;
pthread_attr_t attr;
pthread_t reader;
int ret;
// Initialize mutex attributes
if ((ret = pthread_mutexattr_init(&mutex_attr)) != 0) {
fprintf(stderr, "Error initializing mutex attributes: %d\n", ret);
return 1;
}
// Initialize mutex
if ((ret = pthread_mutex_init(&mutex, &mutex_attr)) != 0) {
fprintf(stderr, "Error initializing mutex: %d\n", ret);
return 1;
}
// Initialize thread attributes
if ((ret = pthread_attr_init(&attr)) != 0) {
fprintf(stderr, "Error initializing thread attributes: %d\n", ret);
cleanup_resources();
return 1;
}
// Create reader thread
if ((ret = pthread_create(&reader, &attr, reader_function, 0)) != 0) {
fprintf(stderr, "Error creating thread: %d\n", ret);
cleanup_resources();
return 1;
}
writer_function();
// Wait for reader thread to finish
if ((ret = pthread_join(reader, 0)) != 0) {
fprintf(stderr, "Error joining thread: %d\n", ret);
cleanup_resources();
return 1;
}
cleanup_resources();
printf("Main thread finished!\n");
return 0;
}
void writer_function(void){
char a=0;
int count=0;
while( a != 'q' ){
pthread_mutex_lock( &mutex );
if ( !buffer_has_item ){
a = make_new_item();
buffer=a;
buffer_has_item = 1;
printf("Thread 1: buffer: '%c', loop count=%d\n", a, count);
count=0;
}
else
count++;
pthread_mutex_unlock( &mutex );
}
}
void* reader_function(void *ptr){
char a=0;
int count=0;
while(a != 'q'){
pthread_mutex_lock( &mutex );
if ( buffer_has_item ){
a=buffer;
if ( a != 'q' )
consume_item(a,count);
buffer_has_item = 0;
count=0;
}
else
count++;
pthread_mutex_unlock(&mutex);
}
printf("Reader thread finished\n");
return 0;
}
int make_new_item(){
static int buffer='a';
return buffer++;
}
void consume_item(char a, int count){
printf("Thread 2: buffer read with '%c', loop count=%d\n", a, count);
}

103
ex06/aufgabe2.c Normal file
View File

@ -0,0 +1,103 @@
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
// Function prototypes
int make_new_item(void);
void *reader_function(void *);
void writer_function(void);
// Shared resources
char buffer;
int buffer_has_item = 0;
pthread_mutex_t mutex;
pthread_cond_t cond_buffer_empty;
pthread_cond_t cond_buffer_full;
void cleanup_resources() {
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond_buffer_empty);
pthread_cond_destroy(&cond_buffer_full);
}
int main(int argc, char *argv[]) {
pthread_mutexattr_t mutex_attr;
pthread_attr_t attr;
pthread_t reader;
int ret;
// Initialize mutex and condition variables
pthread_mutexattr_init(&mutex_attr);
pthread_mutex_init(&mutex, &mutex_attr);
pthread_cond_init(&cond_buffer_empty, NULL);
pthread_cond_init(&cond_buffer_full, NULL);
pthread_attr_init(&attr);
// Create reader thread
pthread_create(&reader, &attr, reader_function, 0);
// Run writer function in the main thread
writer_function();
// Wait for reader thread to finish
pthread_join(reader, 0);
// Clean up
cleanup_resources();
printf("Main thread finished!\n");
return 0;
}
void writer_function(void) {
char a = 0;
while (a != 'q') {
pthread_mutex_lock(&mutex);
// Wait until the buffer is empty
while (buffer_has_item) {
pthread_cond_wait(&cond_buffer_empty, &mutex);
}
a = make_new_item();
buffer = a;
buffer_has_item = 1;
printf("Thread 1: buffer: '%c'\n", a);
// Signal the reader that the buffer is full
pthread_cond_signal(&cond_buffer_full);
pthread_mutex_unlock(&mutex);
}
}
void *reader_function(void *ptr) {
char a = 0;
while (a != 'q') {
pthread_mutex_lock(&mutex);
// Wait until the buffer is full
while (!buffer_has_item) {
pthread_cond_wait(&cond_buffer_full, &mutex);
}
// Read the item from the buffer
a = buffer;
if (a != 'q') {
printf("Thread 2: buffer read with '%c'\n", a);
}
buffer_has_item = 0;
// Signal the producer that the buffer is empty
pthread_cond_signal(&cond_buffer_empty);
pthread_mutex_unlock(&mutex);
}
printf("Reader thread finished\n");
return 0;
}
int make_new_item() {
static int buffer = 'a';
return buffer++;
}

84
ex06/aufgabe3.c Normal file
View File

@ -0,0 +1,84 @@
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
// Function prototypes
int make_new_item(void);
void consume_item(char a, int count);
void *reader_function(void *);
void writer_function(void);
// Shared resources
char buffer;
sem_t empty; // Tracks empty slots
sem_t full; // Tracks filled slots
void cleanup_resources() {
sem_destroy(&empty);
sem_destroy(&full);
}
int main(int argc, char *argv[]) {
pthread_attr_t attr;
pthread_t reader;
// Initialize semaphores
// first 0 is for shared between threads, second 0 is for the initial value
// first 1 would mean that the semaphore is shared between processes
sem_init(&empty, 0, 1); // Initially, buffer is empty (1 empty slot)
sem_init(&full, 0, 0); // Initially, buffer is not full (0 filled slots)
pthread_attr_init(&attr);
pthread_create(&reader, &attr, reader_function, 0);
writer_function();
pthread_join(reader, 0);
cleanup_resources();
printf("Main thread finished!\n");
return 0;
}
void writer_function(void) {
char a = 0;
while (a != 'q') {
sem_wait(&empty);
a = make_new_item();
buffer = a;
printf("Thread 1: buffer: '%c'\n", a);
// Signal that the buffer is full
sem_post(&full);
}
}
void *reader_function(void *ptr) {
char a = 0;
while (a != 'q') {
sem_wait(&full);
a = buffer;
if (a != 'q') {
consume_item(a, 0);
}
sem_post(&empty);
}
printf("Reader thread finished\n");
return 0;
}
int make_new_item() {
static int buffer = 'a';
return buffer++;
}
void consume_item(char a, int count) {
printf("Thread 2: buffer read with '%c'\n", a);
}

103
ex06/aufgabe4.c Normal file
View File

@ -0,0 +1,103 @@
#include <pthread.h>
#include <stdio.h>
//#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <semaphore.h>
//#include <limits.h>
#include <sched.h>
#define MAX_THREADS 50
#define MAX_REGION_ENTRIES 10
void* thread_function(void *ptr);
void enter_region(size_t id);
void leave_region(size_t id);
int cancel_threads = 0;
sem_t region_semaphore;
pthread_mutex_t region_mutex = PTHREAD_MUTEX_INITIALIZER;
size_t regionentries[MAX_REGION_ENTRIES];
int main(int argc, char *argv[]) {
pthread_attr_t attr;
pthread_t threads[MAX_THREADS];
size_t i, counter = 0;
// 0=local process, MAX_REGION_ENTRIES=initial state
if ( sem_init( &region_semaphore, 0, MAX_REGION_ENTRIES ) == 0 ) {
if ( pthread_attr_init( &attr ) == 0 ) {
for (i=0; i<MAX_THREADS; i++) {
if ( pthread_create( &(threads[counter]), &attr, thread_function, (void*)(i+1)) == 0 )
counter++;
}
scanf("%d", &cancel_threads); // set cancel condition
for (i=0;i<counter;i++) {
pthread_join( threads[i], 0);
}
}
sem_destroy( &region_semaphore);
}
printf("Main thread finished!\n");
}
void* thread_function(void *ptr)
{
size_t threadid=(size_t)ptr;
time_t t;
while( ! cancel_threads ){
enter_region(threadid);
t=time(0); // short wait (passive)
usleep((localtime(&t)->tm_sec+localtime(&t)->tm_min)*1000 );
leave_region(threadid);
sched_yield(); // yield CPU
}
printf("Thread %zu finished!\n", threadid);
return 0;
}
void print_region_entries() {
int i;
printf("Threads in region: ");
for (i=0; i<MAX_REGION_ENTRIES; i++)
printf("%zu ", regionentries[i]);
printf("\n");
for(i=0;i<1000000;i++) // short wait (active)
i;
}
void enter_region(size_t id) {
int i;
sem_wait( &region_semaphore );
pthread_mutex_lock(&region_mutex);
for (i=0;i<MAX_REGION_ENTRIES;i++) {
if ( regionentries[i]==0 ) {
regionentries[i]=id;
break;
}
}
print_region_entries();
pthread_mutex_unlock(&region_mutex);
}
void leave_region(size_t id)
{
int i;
pthread_mutex_lock(&region_mutex);
for (i=0;i<MAX_REGION_ENTRIES;i++) {
if ( regionentries[i]==id )
{ regionentries[i]=0;
break;
}
}
print_region_entries();
pthread_mutex_unlock(&region_mutex);
sem_post( &region_semaphore );
}

63
ex07/aufgabe1.c Normal file
View File

@ -0,0 +1,63 @@
// Compiler call: gccc aufgabe1.c -lpthread
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#define LOOPCOUNT 200
void* reader_function(void*);
void writer_function(void);
int buffer_a, buffer_b;
pthread_mutex_t mutex_a, mutex_b;
int main(int argc, char* argv[]) {
pthread_mutexattr_t mutex_attr;
pthread_attr_t attr;
pthread_t reader;
if (pthread_mutexattr_init(&mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_a, &mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_b, &mutex_attr) == 0) {
if (pthread_attr_init(&attr) == 0) {
if (pthread_create(&reader, &attr, reader_function, 0) == 0) {
writer_function();
pthread_join(reader, 0);
}
}
pthread_mutex_destroy(&mutex_b);
}
pthread_mutex_destroy(&mutex_a);
}
}
printf("Main thread finished!\n");
return 0;
}
void writer_function(void) {
int i;
for (i = 0; i < LOOPCOUNT; i++) {
pthread_mutex_lock(&mutex_a);
buffer_a = i;
printf("Writer: Buffer a is : %d,\n", buffer_a);
pthread_mutex_lock(&mutex_b);
buffer_b = buffer_a;
printf("Writer: Buffer b is : %d,\n", buffer_b);
pthread_mutex_unlock(&mutex_b);
pthread_mutex_unlock(&mutex_a);
}
}
void* reader_function(void* ptr) {
int i;
for (i = 0; i < LOOPCOUNT; i++) {
pthread_mutex_lock(&mutex_b);
printf("Reader: Buffer a is : %d,\n", buffer_a);
pthread_mutex_lock(&mutex_a);
printf("Reader: Buffer a+b is : %d,\n", buffer_b + buffer_a);
pthread_mutex_unlock(&mutex_a);
pthread_mutex_unlock(&mutex_b);
}
printf("Reader thread finished\n");
return 0;
}

63
ex07/aufgabe1_improved.c Normal file
View File

@ -0,0 +1,63 @@
// Compiler call: gccc aufgabe1.c -lpthread
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#define LOOPCOUNT 200
void* reader_function(void*);
void writer_function(void);
int buffer_a, buffer_b;
pthread_mutex_t mutex_a, mutex_b;
int main(int argc, char* argv[]) {
pthread_mutexattr_t mutex_attr;
pthread_attr_t attr;
pthread_t reader;
if (pthread_mutexattr_init(&mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_a, &mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_b, &mutex_attr) == 0) {
if (pthread_attr_init(&attr) == 0) {
if (pthread_create(&reader, &attr, reader_function, 0) == 0) {
writer_function();
pthread_join(reader, 0);
}
}
pthread_mutex_destroy(&mutex_b);
}
pthread_mutex_destroy(&mutex_a);
}
}
printf("Main thread finished!\n");
return 0;
}
void writer_function(void) {
int i;
for (i = 0; i < LOOPCOUNT; i++) {
pthread_mutex_lock(&mutex_a);
buffer_a = i;
printf("Writer: Buffer a is : %d,\n", buffer_a);
pthread_mutex_lock(&mutex_b);
buffer_b = buffer_a;
printf("Writer: Buffer b is : %d,\n", buffer_b);
pthread_mutex_unlock(&mutex_b);
pthread_mutex_unlock(&mutex_a);
}
}
void* reader_function(void* ptr) {
int i;
for (i = 0; i < LOOPCOUNT; i++) {
pthread_mutex_lock(&mutex_a);
printf("Reader: Buffer a+b is : %d,\n", buffer_b + buffer_a);
pthread_mutex_unlock(&mutex_a);
pthread_mutex_lock(&mutex_b);
printf("Reader: Buffer a is : %d,\n", buffer_a);
pthread_mutex_unlock(&mutex_b);
}
printf("Reader thread finished\n");
return 0;
}

168
ex07/aufgabe2.c Normal file
View File

@ -0,0 +1,168 @@
// Compiler call: cc -o aufgabe2 aufgabe2.c -lpthread
#define _GNU_SOURCE
#include <pthread.h> // pthread_*
#include <sched.h> // cpu_set_t , CPU_SET
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // strcat
#include <time.h> // nanosleep
#include <unistd.h>
#define LOOPCOUNT 15
void* tH(void*);
void* tL(void*);
void set_cpu_affinity();
pthread_mutex_t mutex_dbg; // buffer mutex (debug output)
pthread_mutex_t mutex_cs; // crit. section mutex
char buffer[10000] = "";
int main(int argc, char* argv[]) {
pthread_mutexattr_t mutex_attr;
pthread_t thread_H, thread_L;
pthread_attr_t attr_H, attr_L;
struct sched_param param_H, param_L;
int policy_father;
struct sched_param param_father;
int i, j;
set_cpu_affinity(); // bind to CPU core 0
// Father sched
pthread_getschedparam(pthread_self(), &policy_father, &param_father);
param_father.sched_priority = sched_get_priority_min(SCHED_RR);
pthread_setschedparam(pthread_self(), SCHED_RR, &param_father);
if (pthread_mutexattr_init(&mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_dbg, &mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_cs, &mutex_attr) == 0) {
if (pthread_attr_init(&attr_H) == 0) {
if (pthread_attr_init(&attr_L) == 0) {
// T_H sched
pthread_attr_setschedpolicy(&attr_H, SCHED_RR);
pthread_attr_getschedparam(&attr_H, &param_H);
param_H.sched_priority = sched_get_priority_min(SCHED_RR);
pthread_attr_setschedparam(&attr_H, &param_H);
pthread_attr_setinheritsched(&attr_H, PTHREAD_EXPLICIT_SCHED);
// T_L sched
pthread_attr_setschedpolicy(&attr_L, SCHED_RR);
pthread_attr_getschedparam(&attr_L, &param_L);
param_L.sched_priority = sched_get_priority_min(SCHED_RR) + 1;
pthread_attr_setschedparam(&attr_L, &param_L);
pthread_attr_setinheritsched(&attr_L, PTHREAD_EXPLICIT_SCHED);
if (pthread_create(&thread_L, &attr_L, tL, 0) == 0) {
nanosleep((const struct timespec[]){{0, 10000000L}}, NULL);
if (pthread_create(&thread_H, &attr_H, tH, 0) == 0) {
pthread_join(thread_H, 0);
}
pthread_join(thread_L, 0);
}
}
}
pthread_mutex_destroy(&mutex_dbg);
pthread_mutex_destroy(&mutex_cs);
}
}
}
printf("%s", buffer);
return 0;
}
void* tH(void* ptr) {
set_cpu_affinity(); // bind to CPU core 0
int i, j;
// Thread T_H
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_H. Attempting to lock mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
pthread_mutex_lock(&mutex_cs);
//
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_H has locked mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
//
for (i = 0; i < LOOPCOUNT; i++) {
for (j = 0; j < 1000000; j++) {
;
} // busy wait
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "I am Thread T_H!\n");
pthread_mutex_unlock(&mutex_dbg);
}
//
pthread_mutex_unlock(&mutex_cs);
return 0;
}
void* tL(void* ptr) {
set_cpu_affinity(); // bind to CPU core 0
int i, j;
// Thread T_L
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_L. Attempting to lock mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
pthread_mutex_lock(&mutex_cs);
//
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_L has locked mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
//
for (i = 0; i < LOOPCOUNT; i++) {
for (j = 0; j < 1000000; j++) {
;
} // busy wait
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "I am Thread T_L!\n");
pthread_mutex_unlock(&mutex_dbg);
}
//
pthread_mutex_unlock(&mutex_cs);
return 0;
}
void set_cpu_affinity() {
// we can set one or more bits here, each one representing a single CPU
cpu_set_t cpuset;
// the CPU we whant to use (core 0)
int cpu = 1;
CPU_ZERO(&cpuset); // clears the cpuset
CPU_SET(cpu, &cpuset); // set CPU 0 on cpuset
/*
* cpu affinity for the calling thread
* first parameter is the pid, 0 = calling thread
* second parameter is the size of your cpuset
* third param is the cpuset in which your thread will be
* placed. Each bit represents a CPU
*/
sched_setaffinity(0, sizeof(cpuset), &cpuset);
// pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
}

132
ex07/aufgabe2_gpt.c Normal file
View File

@ -0,0 +1,132 @@
#define _GNU_SOURCE
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define LOOPCOUNT 15
void* tH(void*);
void* tL(void*);
void set_cpu_affinity(int cpu);
pthread_mutex_t mutex_dbg; // buffer mutex (debug output)
pthread_mutex_t mutex_cs; // critical section mutex
char buffer[10000] = "";
int main(int argc, char* argv[]) {
pthread_mutexattr_t mutex_attr;
pthread_t thread_H, thread_L;
pthread_attr_t attr_H, attr_L;
struct sched_param param_H, param_L;
int policy_father;
struct sched_param param_father;
set_cpu_affinity(0); // bind to CPU core 0
// Father sched
pthread_getschedparam(pthread_self(), &policy_father, &param_father);
param_father.sched_priority = sched_get_priority_min(SCHED_RR);
pthread_setschedparam(pthread_self(), SCHED_RR, &param_father);
if (pthread_mutexattr_init(&mutex_attr) == 0) {
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT); // Enable priority inheritance
if (pthread_mutex_init(&mutex_dbg, &mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_cs, &mutex_attr) == 0) {
if (pthread_attr_init(&attr_H) == 0) {
if (pthread_attr_init(&attr_L) == 0) {
// T_H sched
pthread_attr_setschedpolicy(&attr_H, SCHED_RR);
param_H.sched_priority = sched_get_priority_max(SCHED_RR); // Higher priority
pthread_attr_setschedparam(&attr_H, &param_H);
pthread_attr_setinheritsched(&attr_H, PTHREAD_EXPLICIT_SCHED);
// T_L sched
pthread_attr_setschedpolicy(&attr_L, SCHED_RR);
param_L.sched_priority = sched_get_priority_min(SCHED_RR); // Lower priority
pthread_attr_setschedparam(&attr_L, &param_L);
pthread_attr_setinheritsched(&attr_L, PTHREAD_EXPLICIT_SCHED);
if (pthread_create(&thread_L, &attr_L, tL, NULL) == 0) {
nanosleep((const struct timespec[]){{0, 10000000L}}, NULL);
if (pthread_create(&thread_H, &attr_H, tH, NULL) == 0) {
pthread_join(thread_H, NULL);
}
pthread_join(thread_L, NULL);
}
}
}
pthread_mutex_destroy(&mutex_dbg);
pthread_mutex_destroy(&mutex_cs);
}
}
}
printf("%s", buffer);
return 0;
}
void* tH(void* ptr) {
set_cpu_affinity(0); // bind to CPU core 0
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_H. Attempting to lock mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
pthread_mutex_lock(&mutex_cs);
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_H has locked mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
for (int i = 0; i < LOOPCOUNT; i++) {
for (int j = 0; j < 1000000; j++) {
; // busy wait
}
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "I am Thread T_H!\n");
pthread_mutex_unlock(&mutex_dbg);
}
pthread_mutex_unlock(&mutex_cs);
return NULL;
}
void* tL(void* ptr) {
set_cpu_affinity(0); // bind to CPU core 0
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_L. Attempting to lock mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
pthread_mutex_lock(&mutex_cs);
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_L has locked mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
for (int i = 0; i < LOOPCOUNT; i++) {
for (int j = 0; j < 1000000; j++) {
; // busy wait
}
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "I am Thread T_L!\n");
pthread_mutex_unlock(&mutex_dbg);
}
pthread_mutex_unlock(&mutex_cs);
return NULL;
}
void set_cpu_affinity(int cpu) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu, &cpuset);
sched_setaffinity(0, sizeof(cpuset), &cpuset);
}

170
ex07/aufgabe2_improved.c Normal file
View File

@ -0,0 +1,170 @@
// Compiler call: cc -o aufgabe2 aufgabe2.c -lpthread
// requires sudod to run
#define _GNU_SOURCE
#include <pthread.h> // pthread_*
#include <sched.h> // cpu_set_t , CPU_SET
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // strcat
#include <time.h> // nanosleep
#include <unistd.h>
#define LOOPCOUNT 15
void* tH(void*);
void* tL(void*);
void set_cpu_affinity();
pthread_mutex_t mutex_dbg; // buffer mutex (debug output)
pthread_mutex_t mutex_cs; // crit. section mutex
char buffer[10000] = "";
int main(int argc, char* argv[]) {
pthread_mutexattr_t mutex_attr;
pthread_t thread_H, thread_L;
pthread_attr_t attr_H, attr_L;
struct sched_param param_H, param_L;
int policy_father;
struct sched_param param_father;
int i, j;
set_cpu_affinity(); // bind to CPU core 0
// Father sched
pthread_getschedparam(pthread_self(), &policy_father, &param_father);
param_father.sched_priority = sched_get_priority_min(SCHED_RR);
pthread_setschedparam(pthread_self(), SCHED_RR, &param_father);
if (pthread_mutexattr_init(&mutex_attr) == 0) {
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_INHERIT); // Enable priority inheritance
if (pthread_mutex_init(&mutex_dbg, &mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_cs, &mutex_attr) == 0) {
if (pthread_attr_init(&attr_H) == 0) {
if (pthread_attr_init(&attr_L) == 0) {
// T_H sched
pthread_attr_setschedpolicy(&attr_H, SCHED_RR);
pthread_attr_getschedparam(&attr_H, &param_H);
param_H.sched_priority = sched_get_priority_min(SCHED_RR) + 1;
pthread_attr_setschedparam(&attr_H, &param_H);
pthread_attr_setinheritsched(&attr_H, PTHREAD_EXPLICIT_SCHED);
// T_L sched
pthread_attr_setschedpolicy(&attr_L, SCHED_RR);
pthread_attr_getschedparam(&attr_L, &param_L);
param_L.sched_priority = sched_get_priority_min(SCHED_RR);
pthread_attr_setschedparam(&attr_L, &param_L);
pthread_attr_setinheritsched(&attr_L, PTHREAD_EXPLICIT_SCHED);
if (pthread_create(&thread_L, &attr_L, tL, 0) == 0) {
nanosleep((const struct timespec[]){{0, 10000000L}}, NULL);
if (pthread_create(&thread_H, &attr_H, tH, 0) == 0) {
pthread_join(thread_H, 0);
}
pthread_join(thread_L, 0);
}
}
}
pthread_mutex_destroy(&mutex_dbg);
pthread_mutex_destroy(&mutex_cs);
}
}
}
printf("%s", buffer);
return 0;
}
void* tH(void* ptr) {
set_cpu_affinity(); // bind to CPU core 0
int i, j;
// Thread T_H
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_H. Attempting to lock mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
pthread_mutex_lock(&mutex_cs);
//
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_H has locked mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
//
for (i = 0; i < LOOPCOUNT; i++) {
for (j = 0; j < 1000000; j++) {
;
} // busy wait
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "I am Thread T_H!\n");
pthread_mutex_unlock(&mutex_dbg);
}
//
pthread_mutex_unlock(&mutex_cs);
return 0;
}
void* tL(void* ptr) {
set_cpu_affinity(); // bind to CPU core 0
int i, j;
// Thread T_L
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_L. Attempting to lock mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
pthread_mutex_lock(&mutex_cs);
//
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "Thread T_L has locked mutex_cs!\n");
pthread_mutex_unlock(&mutex_dbg);
//
for (i = 0; i < LOOPCOUNT; i++) {
for (j = 0; j < 1000000; j++) {
;
} // busy wait
pthread_mutex_lock(&mutex_dbg);
strcat(buffer, "I am Thread T_L!\n");
pthread_mutex_unlock(&mutex_dbg);
}
//
pthread_mutex_unlock(&mutex_cs);
return 0;
}
void set_cpu_affinity() {
// we can set one or more bits here, each one representing a single CPU
cpu_set_t cpuset;
// the CPU we whant to use (core 0)
int cpu = 1;
CPU_ZERO(&cpuset); // clears the cpuset
CPU_SET(cpu, &cpuset); // set CPU 0 on cpuset
/*
* cpu affinity for the calling thread
* first parameter is the pid, 0 = calling thread
* second parameter is the size of your cpuset
* third param is the cpuset in which your thread will be
* placed. Each bit represents a CPU
*/
sched_setaffinity(0, sizeof(cpuset), &cpuset);
// pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
}

72
ex07/aufgabe5.c Normal file
View File

@ -0,0 +1,72 @@
// Compiler call: gcc -o aufgabe1 aufgabe1.c -lpthread
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#define LOOPCOUNT 200
void* reader_function(void*);
void writer_function(void);
int buffer_a, buffer_b;
pthread_mutex_t mutex_a, mutex_b;
int main(int argc, char* argv[]) {
pthread_mutexattr_t mutex_attr;
pthread_attr_t attr;
pthread_t reader;
// Initialize mutex attributes
if (pthread_mutexattr_init(&mutex_attr) == 0) {
// Set the mutex protocol to PCP
pthread_mutexattr_setprotocol(&mutex_attr, PTHREAD_PRIO_PROTECT);
// Set the priority ceiling for each mutex
pthread_mutexattr_setprioceiling(&mutex_attr, 10); // Example priority ceiling
if (pthread_mutex_init(&mutex_a, &mutex_attr) == 0) {
if (pthread_mutex_init(&mutex_b, &mutex_attr) == 0) {
if (pthread_attr_init(&attr) == 0) {
// Create the reader thread
if (pthread_create(&reader, &attr, reader_function, 0) == 0) {
writer_function();
pthread_join(reader, 0);
}
}
pthread_mutex_destroy(&mutex_b);
}
pthread_mutex_destroy(&mutex_a);
}
}
printf("Main thread finished!\n");
return 0;
}
void writer_function(void) {
int i;
for (i = 0; i < LOOPCOUNT; i++) {
pthread_mutex_lock(&mutex_a);
buffer_a = i;
printf("Writer: Buffer a is : %d,\n", buffer_a);
pthread_mutex_lock(&mutex_b);
buffer_b = buffer_a;
printf("Writer: Buffer b is : %d,\n", buffer_b);
pthread_mutex_unlock(&mutex_b);
pthread_mutex_unlock(&mutex_a);
}
}
void* reader_function(void* ptr) {
int i;
for (i = 0; i < LOOPCOUNT; i++) {
pthread_mutex_lock(&mutex_a);
printf("Reader: Buffer a+b is : %d,\n", buffer_b + buffer_a);
pthread_mutex_unlock(&mutex_a);
pthread_mutex_lock(&mutex_b);
printf("Reader: Buffer a is : %d,\n", buffer_a);
pthread_mutex_unlock(&mutex_b);
}
printf("Reader thread finished\n");
return 0;
}

View File

@ -0,0 +1,80 @@
Everything in <> is variable and depends on your system / your intention
The prompt is always shown in your shell:
<user>@<host>:<path> $
<user> is the user that is running the shell (important if you work with multiple user accounts e.g. root and user)
<host> is the hostname of the PC the shell is running on (important if you connect to remote machines)
<path> is the path where you are currently located at
As soon as the prompt is shown you can enter any command.
The 'TAB' key autocompletes commands and paths as soon as there is no ambiguity.
If multiple possibilities exist 2x'TAB' will diplay them.
################################################################################
Commands you should know:
################################################################################
man <command> show manual for the command <command>
exit with 'q'
ls <options> list directory (mind the space between command and options, this is always the case)
ls <options> is empty just list the directory
ls -l <options> is '-l' list directory with more details (permissions owner group size date time filename)
ls -a <options> is '-a' list directory including hidden files
ls -a -l <options> are '-a -l' list directory (also hidden files) with more details (mind the space again)
cd <path> change directory (relative to your current directory)
cd /<path> change directory (absolute [from the file system root])
mkdir <folder> create folder
mkdir -p <path> create all folders to this path
rm <file> remove the file
rm -r <folder> remove folder (recursive)
chmod <permissions> <file> change file permissions (read, write, execute) for owner, group and others
Permissions are typically shown this way: rwxrwxrwx
first entry (rwx) is for the owner of the file/folder
second entry (rwx) is for the group this file/folder belongs to
third entry (rwx) is for all others
missing permissions are shown with a dash '-'
rwxr-xr-- means the owner can do anything; the group can read and execute; all others can only read
chmod +x <file> make file executable for everyone (+w -> writable; +r -> readable)
chmod -x <file remove the right to execute for everyone (-w -> writable; -r -> readable)
chmod u+x <file> make file executable for the owner (u=owner, g=group, o=others a=all)
chmod u-x <file remove the right to execute for the owner
cat <file> read file contents (prints the whole file to the terminal)
less <file> read file contents (page by page) [exit with 'q']
echo <text> print <text> to the terminal
echo <text> > <file> print <text> to the file <file> (note the '>' before <file> )
using the operator '>' the output of every program can be written to a file
what would 'ls -l > out' do?
nano <file> edit a file with the "nano" CLI text editor, creates the file if not existing
./<prog> executes a program in the current directory
/.../<prog> executes a program in an absolute path (from root)
/.../<prog> & executes a program in background
/.../<prog> &>/dev/null executes a program silently with stdout and stderr redirected to /dev/null
/.../<prog> &>/dev/null & executes a program silently and in background
chrt -f <prio> <prog> starts <prog> directly with RT priority <prio>, sets policy SCHED_FIFO
chrt -r <prio> <prog> starts <prog> directly with RT priority <prio>, sets policy SCHED_RR
chrt -f -p <prio> <id> changes RT priority of running process/thread ID <id> to <prio>, sets policy SCHED_FIFO
chrt -r -p <prio> <id> changes RT priority of running process/thread ID <id> to <prio>, sets policy SCHED_RR
sudo <cmd> executes <cmd> as root user
################################################################################
Paths you need to know:
################################################################################
/ the root of your file system tree
/home/<user>/ the home directory of the currently logged in user <user>. Shorthand: '~'
/sys/class/gpio/ access to the gpio pins (if available) - see sysfs

87
lab/square_wave.c Normal file
View File

@ -0,0 +1,87 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ITERATIONS 100000
// Shared variables
pthread_mutex_t lock;
pthread_cond_t cond;
int signal_flag = 0; // 0 = LOW, 1 = HIGH
int counter = 0;
void* high_thread(void* arg) {
while (1) {
pthread_mutex_lock(&lock);
// Wait for turn
while (signal_flag != 1) {
pthread_cond_wait(&cond, &lock);
}
// Critical section
if (counter >= ITERATIONS) {
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
exit(0);
}
printf("%d: HIGH\n", counter);
counter++;
signal_flag = 0;
// Signal the other thread
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
}
return NULL;
}
void* low_thread(void* arg) {
while (1) {
pthread_mutex_lock(&lock);
// Wait for turn
while (signal_flag != 0) {
pthread_cond_wait(&cond, &lock);
}
// Critical section
if (counter >= ITERATIONS) {
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
exit(0);
}
printf("%d: LOW\n", counter);
counter++;
signal_flag = 1;
// Signal the other thread
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
}
return NULL;
}
int main() {
pthread_t high_tid, low_tid;
// Initialize synchronization primitives
pthread_mutex_init(&lock, NULL);
pthread_cond_init(&cond, NULL);
// Create threads
pthread_create(&high_tid, NULL, high_thread, NULL);
pthread_create(&low_tid, NULL, low_thread, NULL);
// Wait for threads to finish
pthread_join(high_tid, NULL);
pthread_join(low_tid, NULL);
// Cleanup
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
return 0;
}