Add initial shared memory object functions
This commit is contained in:
parent
435eb6dba6
commit
9a652f4d4e
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,3 +8,5 @@ http/client
|
|||||||
http/server
|
http/server
|
||||||
mygrep/mygrep
|
mygrep/mygrep
|
||||||
cpair/cpair
|
cpair/cpair
|
||||||
|
fb_arc_set/supervisor
|
||||||
|
fb_arc_set/generator
|
||||||
|
@ -5,16 +5,16 @@ TARGET_2 = supervisor
|
|||||||
|
|
||||||
all: $(TARGET_1).c $(TARGET_2).c
|
all: $(TARGET_1).c $(TARGET_2).c
|
||||||
$(CC) $(CFLAGS) $(TARGET_1).c $(TARGET_2).c
|
$(CC) $(CFLAGS) $(TARGET_1).c $(TARGET_2).c
|
||||||
$(CC) $(TARGET_1).o -o $(TARGET_1)
|
$(CC) $(TARGET_1).o -o $(TARGET_1) -lrt
|
||||||
$(CC) $(TARGET_2).o -o $(TARGET_2)
|
$(CC) $(TARGET_2).o -o $(TARGET_2) -lrt
|
||||||
|
|
||||||
generator: $(TARGET_1).c
|
generator: $(TARGET_1).c
|
||||||
$(CC) $(CFLAGS) $(TARGET_1).c
|
$(CC) $(CFLAGS) $(TARGET_1).c
|
||||||
$(CC) $(TARGET_1).o -o $(TARGET_1)
|
$(CC) $(TARGET_1).o -o $(TARGET_1) -lrt
|
||||||
|
|
||||||
supervisor: $(TARGET_2).c
|
supervisor: $(TARGET_2).c
|
||||||
$(CC) $(CFLAGS) $(TARGET_2).c
|
$(CC) $(CFLAGS) $(TARGET_2).c
|
||||||
$(CC) $(TARGET_2).o -o $(TARGET_2)
|
$(CC) $(TARGET_2).o -o $(TARGET_2) -lrt
|
||||||
|
|
||||||
install:
|
install:
|
||||||
cp $(TARGET_1) /usr/local/bin/graph-$(TARGET_1)
|
cp $(TARGET_1) /usr/local/bin/graph-$(TARGET_1)
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* @file generator.c
|
||||||
|
* @author Ivaylo Ivanov 11777707
|
||||||
|
* @date 11.01.2018
|
||||||
|
*
|
||||||
|
* @brief Generator program module.
|
||||||
|
*
|
||||||
|
* The generator program takes a graph as input. The program repeatedly generates a random solution
|
||||||
|
* to the problem as described on the first page and writes its result to the circular buffer. It repeats this
|
||||||
|
* procedure until it is notified by the supervisor to terminate.
|
||||||
|
* The generator program takes as arguments the set of edges of the graph.
|
||||||
|
* Each positional argument is one edge; at least one edge must be given. An edge is specified by a string,
|
||||||
|
* with the indices of the two nodes it connects separated by a -. Since the graph is directed, the edge starts
|
||||||
|
* at the first node and leads to the second node. Note that the number of nodes of the graph is implicitly
|
||||||
|
* provided through the indices in the edges. In the example above the generator program is called with
|
||||||
|
* the graph shown on the first page.
|
||||||
|
* The generator uses the algorithm described on the first page to generate random feedback arc sets for the
|
||||||
|
* given graph. It writes these feedback arc sets to the circular buffer, one at a time; therefore a feedback
|
||||||
|
* arc set is a single element of the circular buffer. The generator may produce debug output, describing
|
||||||
|
* the feedback arc sets which it writes to the circular buffer.
|
||||||
|
*
|
||||||
|
* SYNOPSIS
|
||||||
|
* generator EDGE1 EDGE2 ...
|
||||||
|
*
|
||||||
|
* EXAMPLE
|
||||||
|
* generator 0-1 1-2 1-3 1-4 2-4 3-6 4-3 4-5 6-0
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
#include "shared/shm.c"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if(argc > 1) {
|
||||||
|
fprintf(stderr, "ERROR: Command takes no arguments");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* terminate_shm = open_shm(TERMINATE_SHM, TERMINATE_SHM_SIZE);
|
||||||
|
|
||||||
|
write_to_shm(terminate_shm, "1", TERMINATE_SHM_SIZE);
|
||||||
|
puts(terminate_shm);
|
||||||
|
close_shm(terminate_shm, TERMINATE_SHM_SIZE);
|
||||||
|
destroy_shm(TERMINATE_SHM);
|
||||||
|
}
|
||||||
|
|
52
fb_arc_set/shared/shm.c
Normal file
52
fb_arc_set/shared/shm.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define TERMINATE_SHM "/terminate"
|
||||||
|
#define TERMINATE_SHM_SIZE 8
|
||||||
|
|
||||||
|
void* open_shm(char *shm_name, size_t shm_size) {
|
||||||
|
int shmfd = shm_open(shm_name, O_RDWR | O_CREAT, 0600);
|
||||||
|
if(shmfd == -1) {
|
||||||
|
fprintf(stderr, "ERROR: Failed creating shared memory object");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ftruncate(shmfd, shm_size) < 0) {
|
||||||
|
fprintf(stderr, "ERROR: Failed truncating shared memory object");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* shm;
|
||||||
|
shm = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
|
||||||
|
|
||||||
|
if(shm == MAP_FAILED) {
|
||||||
|
fprintf(stderr, "ERROR: Failed mapping shared memory object");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_to_shm(void* shm, char *message, size_t message_size) {
|
||||||
|
memcpy(shm, message, message_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_shm(void* shm, size_t shm_size) {
|
||||||
|
if (munmap(shm, shm_size) == -1) {
|
||||||
|
fprintf(stderr, "ERROR: Failed unmapping shared memory object");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_shm(char *shm_name) {
|
||||||
|
if (shm_unlink(shm_name) == -1) {
|
||||||
|
fprintf(stderr, "ERROR: Failed unlinking shared memory object");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* @file supervisor.c
|
||||||
|
* @author Ivaylo Ivanov 11777707
|
||||||
|
* @date 11.01.2018
|
||||||
|
*
|
||||||
|
* @brief Supervisor program module.
|
||||||
|
*
|
||||||
|
* The supervisor sets up the shared memory and the semaphores and initializes the circular buffer required
|
||||||
|
* for the communication with the generators. It then waits for the generators to write solutions to the
|
||||||
|
* circular buffer.
|
||||||
|
* The supervisor program takes no arguments.
|
||||||
|
* Once initialization is complete, the supervisor reads the solutions from the circular buffer and remembers the best solution so far, i.e. the solution with the least edges. Every time a better solution than the
|
||||||
|
* previous best solution is found, the supervisor writes the new solution to standard output. If a generator
|
||||||
|
* writes a solution with 0 edges to the circular buffer, then the graph is acyclic and the supervisor terminates. Otherwise the supervisor keeps reading results from the circular buffer until it receives a SIGINT
|
||||||
|
* or a SIGTERM signal.
|
||||||
|
* Before terminating, the supervisor notifies all generators that they should terminate as well. This can
|
||||||
|
* be done by setting a variable in the shared memory, which is checked by the generator processes before
|
||||||
|
* writing to the buffer. The supervisor then unlinks all shared resources and exits.
|
||||||
|
*
|
||||||
|
* SYNOPSIS
|
||||||
|
* supervisor
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
#include "shared/shm.c"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if(argc > 1) {
|
||||||
|
fprintf(stderr, "ERROR: Command takes no arguments");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* terminate_shm = open_shm(TERMINATE_SHM, TERMINATE_SHM_SIZE);
|
||||||
|
|
||||||
|
write_to_shm(terminate_shm, "1", TERMINATE_SHM_SIZE);
|
||||||
|
close_shm(terminate_shm, TERMINATE_SHM_SIZE);
|
||||||
|
destroy_shm(TERMINATE_SHM);
|
||||||
|
}
|
Reference in New Issue
Block a user