Create a more modularized code
Co-authored-by: Ezequiel Bellver <ebellver@itba.edu.ar> Co-authored-by: Juan Barmasch <jbarmasch@itba.edu.ar>
This commit is contained in:
parent
e1a06f823d
commit
2ff817394d
18
Makefile
18
Makefile
|
@ -1,7 +1,7 @@
|
|||
CC = gcc
|
||||
CCFLAGS = -Wall -std=c99 -pedantic -g
|
||||
|
||||
OBJECTS = master.o error.o slave.o shr_mem.o view.o solve view
|
||||
OBJECTS = master.o error.o slave.o shr_mem.o view.o siglib.o solve view
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
|
@ -15,10 +15,12 @@ shr_mem.o: shr_mem.c error.h
|
|||
$(CC) $(CCFLAGS) -c shr_mem.c
|
||||
view.o: view.c
|
||||
$(CC) $(CCFLAGS) -c view.c
|
||||
solve: master.o error.o shr_mem.o
|
||||
$(CC) $(CCFLAGS) -o solve master.o error.o shr_mem.o -lrt -lpthread
|
||||
view: view.o error.o shr_mem.o
|
||||
$(CC) $(CCFLAGS) -o view view.o error.o shr_mem.o -lrt -lpthread
|
||||
siglib.o: siglib.c
|
||||
$(CC) $(CCFLAGS) -c siglib.c
|
||||
solve: master.o error.o shr_mem.o siglib.o
|
||||
$(CC) $(CCFLAGS) -o solve master.o error.o shr_mem.o siglib.o -lm -lrt -lpthread
|
||||
view: view.o error.o shr_mem.o siglib.o
|
||||
$(CC) $(CCFLAGS) -o view view.o error.o shr_mem.o siglib.o -lrt -lpthread
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJECTS)
|
||||
|
@ -28,9 +30,9 @@ test:
|
|||
pvs-studio-analyzer analyze
|
||||
plog-converter -a '64:1,2,3;GA:1,2,3;OP:1,2,3' -t tasklist -o report.tasks PVS-Studio.log
|
||||
cppcheck --quiet --enable=all --force --inconclusive .
|
||||
valgrind --leak-check=full ./solve > valgrindSolve.output 2>&1
|
||||
valgrind --leak-check=full ./view ~ > valgrindView.output 2>&1
|
||||
valgrind --leak-check=full ./slave ~ > valgrindSlave.output 2>&1
|
||||
valgrind --leak-check=full --track-origins=yes ./solve HardTest/*.cnf > valgrindSolve.output 2>&1
|
||||
./solve HardTest/*.cnf | valgrind --leak-check=full --show-leak-kinds=all ./view > valgrindView.output 2>&1
|
||||
valgrind --leak-check=full ./slave > valgrindSlave.output 2>&1 < Test/*.cnf
|
||||
|
||||
.PHONY: all clean test
|
||||
|
||||
|
|
22
README.md
22
README.md
|
@ -3,8 +3,13 @@
|
|||
BSSolver (Bottler Sat Solver) es un sistema que resuelve múltiples fórmulas proposicionales en CNF
|
||||
de forma distribuida.
|
||||
|
||||
## Table de contenidos
|
||||
* [Requisitos](#requisitos)
|
||||
* [Compilación](#compilación)
|
||||
* [Ejecución](#ejecución)
|
||||
* [Testeos](#tests)
|
||||
|
||||
## Requisitos
|
||||
## Requisitos <a name="requisitos"></a>
|
||||
|
||||
Debe instalar minisat. Este se encuentra disponible en el repositorio de la vasta mayoría de distribuciones de Linux/macOS.
|
||||
|
||||
|
@ -13,7 +18,7 @@ macOS (con [homebrew](https://brew.sh/)): `brew install minisat`
|
|||
|
||||
Si tiene otra distribución consulte cómo hacerlo.
|
||||
|
||||
## Compilación
|
||||
## Compilación <a name="compilación"></a>
|
||||
|
||||
Para compilar todos los archivos se debe hacer:
|
||||
|
||||
|
@ -21,7 +26,7 @@ Para compilar todos los archivos se debe hacer:
|
|||
make all
|
||||
```
|
||||
|
||||
## Ejecución
|
||||
## Ejecución <a name="ejecución"></a>
|
||||
|
||||
Ahora, tendrá dos ejecutables: `view` y `solve`.
|
||||
|
||||
|
@ -32,7 +37,7 @@ Para ejecutar el programa que se encarga de resolver usted debe pasarle los arch
|
|||
```
|
||||
Este enviará por salida estándar la cantidad de archivos a resolver y su PID, los cuales son necesarios para el programa `view`. Por lo tanto, usted tiene dos posibles modos de uso del sistema:
|
||||
|
||||
1) Enviar el output de solve directamente a view (con el uso de pipes):
|
||||
1) Enviar el output de `solve` directamente a `view` (con el uso de pipes):
|
||||
|
||||
```bash
|
||||
./solve $(CNF_FILES) | ./view
|
||||
|
@ -46,9 +51,14 @@ Este enviará por salida estándar la cantidad de archivos a resolver y su PID,
|
|||
```bash
|
||||
./view $(TOTAL_FILES) $(PID)
|
||||
```
|
||||
Debe notar que dispondrá de 5 segundos para correr el programa `view`.
|
||||
|
||||
## Test
|
||||
3) No correr el proceso `view`.
|
||||
|
||||
Debe notar que en todos los casos se escribirá el output un archivo llamado `ouputFile.txt`.
|
||||
|
||||
Además, dispondrá de 5 segundos para correr el programa `view`.
|
||||
|
||||
## Testeos <a name="tests"></a>
|
||||
|
||||
En orden de realizar los testeos usted debe tener instalado [valgrind](https://valgrind.org/), [cppcheck](http://cppcheck.net/) y [pvs-studio](https://pvs-studio.com/). Luego, puede correr los testeos con:
|
||||
|
||||
|
|
4
error.c
4
error.c
|
@ -1,3 +1,7 @@
|
|||
/*
|
||||
This is a personal academic project. Dear PVS-Studio, please check it.
|
||||
PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
144
master.c
144
master.c
|
@ -1,6 +1,9 @@
|
|||
/*
|
||||
This is a personal academic project. Dear PVS-Studio, please check it.
|
||||
PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
#define _SVID_SOURCE 1
|
||||
//#define _DEFAULT_SOURCE 1
|
||||
|
||||
#define _XOPEN_SOURCE 500
|
||||
#define _POSIX_C_SOURCE 2
|
||||
|
||||
|
@ -8,150 +11,108 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/shm.h>
|
||||
#include "error.h"
|
||||
#include "shr_mem.h"
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define SLAVE_NUM 5
|
||||
#define MAX_SIZE 300
|
||||
#define MAX_PATH_SIZE 100
|
||||
#define MAX_OUTPUT_SIZE (200 + MAX_PATH_SIZE)
|
||||
|
||||
void createPipes(int pipesOutput[SLAVE_NUM][2], int pipesInput[SLAVE_NUM][2]);
|
||||
int writeOutput(char * output, FILE * outputFile, void * shmP, char viewLinked);
|
||||
void closePipes(int pipesInput[SLAVE_NUM][2], int pipesOutput[SLAVE_NUM][2], int slave);
|
||||
char sendTask(struct stat statBuf, char * fileName, int pipesInput[SLAVE_NUM][2], int slave);
|
||||
void changeViewFlag();
|
||||
#include <math.h>
|
||||
#include "master.h"
|
||||
#include "siglib.h"
|
||||
|
||||
static char viewLinked = 0;
|
||||
int slaveNum;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (setvbuf(stdout, NULL, _IONBF, 0) != 0)
|
||||
printSystemError("setvbuf() -- ERROR");
|
||||
|
||||
if (argc == 1)
|
||||
printError("Error: no arguments provided");
|
||||
printError("No arguments provided -- ERROR");
|
||||
|
||||
//sem_unlink("/EMPTY");
|
||||
slaveNum = floor(log2(argc - 1) * 2);
|
||||
slaveNum = (slaveNum < MAX_SLAVES ? slaveNum : MAX_SLAVES);
|
||||
|
||||
FILE * outputFile;
|
||||
if ((outputFile = fopen("outputFile.txt", "w")) == NULL)
|
||||
if ((outputFile = fopen(OUTPUT_NAME, "w")) == NULL)
|
||||
printSystemError("fopen() -- ERROR");
|
||||
|
||||
char * shmPointer;
|
||||
int shmFd;
|
||||
shmFd = createShm((argc - 1) * MAX_OUTPUT_SIZE, &shmPointer);
|
||||
void * shmStart;
|
||||
char * shmPointer, * shmStart;
|
||||
int totalSize = (argc - 1) * MAX_OUTPUT_SIZE;
|
||||
int shmFd = createShm(totalSize);
|
||||
|
||||
printf("%d\n", argc - 1);
|
||||
printf("%d\n", getpid());
|
||||
|
||||
struct sigaction sigAct;
|
||||
sigAct.sa_handler = changeViewFlag;
|
||||
sigAct.sa_flags = 0;
|
||||
if (sigaction(SIGUSR1, &sigAct, NULL) == -1)
|
||||
printSystemError("sigaction() -- ERROR");
|
||||
printf("%d\n%d\n", argc - 1, getpid());
|
||||
|
||||
addSignalHandler(changeViewFlag);
|
||||
sleep(5);
|
||||
blockSignal();
|
||||
|
||||
/*
|
||||
char * shmPointer;
|
||||
int shmFd;
|
||||
void * shmStart;
|
||||
*/
|
||||
if (viewLinked) {
|
||||
shmPointer = mmap(0, (argc - 1) * MAX_OUTPUT_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shmFd, 0);
|
||||
//shmFd = createShm((argc - 1) * MAX_OUTPUT_SIZE, &shmPointer);
|
||||
mapShm(&shmPointer, totalSize, shmFd);
|
||||
shmStart = shmPointer;
|
||||
//close(shmFd);
|
||||
}
|
||||
|
||||
int pipesOutput[SLAVE_NUM][2], pipesInput[SLAVE_NUM][2];
|
||||
createPipes(pipesOutput, pipesInput);
|
||||
int pipesOutput[slaveNum][2], pipesInput[slaveNum][2];
|
||||
createPipesAndSlaves(pipesOutput, pipesInput);
|
||||
|
||||
struct stat statBuf;
|
||||
int tasks = 1;
|
||||
for (int j = 0; tasks <= SLAVE_NUM && tasks < argc; tasks++) {
|
||||
if (sendTask(statBuf, argv[tasks], pipesInput, j++) == 0)
|
||||
for (int j = 0; tasks <= slaveNum && tasks < argc; tasks++) {
|
||||
if (sendTask(argv[tasks], pipesInput, j++) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
char buf[MAX_SIZE];
|
||||
|
||||
fd_set pipesOutputSet;
|
||||
FD_ZERO(&pipesOutputSet);
|
||||
|
||||
int r, readBytes, flag, count;
|
||||
if (tasks != SLAVE_NUM) {
|
||||
for (int k = tasks - 1; k < SLAVE_NUM; k++) {
|
||||
closePipes(pipesInput, pipesOutput, k);
|
||||
char buf[MAX_SIZE], flag;
|
||||
int r, readBytes, count;
|
||||
if (tasks < slaveNum) {
|
||||
for (int k = tasks - 1; k < slaveNum; k++) {
|
||||
closePipes(pipesInput, pipesOutput, k, &pipesOutputSet);
|
||||
}
|
||||
}
|
||||
do {
|
||||
flag = 0;
|
||||
FD_ZERO(&pipesOutputSet);
|
||||
for (int n = 0; n < SLAVE_NUM; n++) {
|
||||
for (int n = 0; n < slaveNum; n++) {
|
||||
if (pipesOutput[n][0] != -1) {
|
||||
FD_SET(pipesOutput[n][0], &pipesOutputSet);
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
if ((count = select(pipesOutput[SLAVE_NUM - 1][1] + 1, &pipesOutputSet, NULL, NULL, NULL)) <= 0)
|
||||
if ((count = select(pipesOutput[slaveNum - 1][1] + 1, &pipesOutputSet, NULL, NULL, NULL)) <= 0)
|
||||
printSystemError("select() -- ERROR");
|
||||
|
||||
for (r = 0; r < SLAVE_NUM && count > 0; r++) {
|
||||
if (FD_ISSET(pipesOutput[r][0], &pipesOutputSet)) {
|
||||
readBytes = 0;
|
||||
do {
|
||||
if ((readBytes += read(pipesOutput[r][0], buf + readBytes, MAX_SIZE)) < 0)
|
||||
printSystemError("read() -- ERROR");
|
||||
} while (buf[readBytes - 1] != '\n');
|
||||
buf[readBytes] = 0;
|
||||
for (r = 0; r < slaveNum && count > 0; r++) {
|
||||
if (FD_ISSET(pipesOutput[r][0], &pipesOutputSet) && pipesOutput[r][0] != -1) {
|
||||
if ((readBytes = read(pipesOutput[r][0], buf, MAX_SIZE)) < 0)
|
||||
printSystemError("read() -- ERROR");
|
||||
buf[readBytes] = '\0';
|
||||
|
||||
// printf("\n%s\n", buf);
|
||||
shmPointer += writeOutput(buf, outputFile, shmPointer, viewLinked);
|
||||
shmPointer += writeOutput(buf, outputFile, shmPointer, r);
|
||||
count--;
|
||||
|
||||
if (tasks < argc) {
|
||||
if (sendTask(statBuf, argv[tasks++], pipesInput, r) == 0)
|
||||
if (sendTask(argv[tasks++], pipesInput, r) == 0)
|
||||
continue;
|
||||
} else {
|
||||
closePipes(pipesInput, pipesOutput, r);
|
||||
closePipes(pipesInput, pipesOutput, r, &pipesOutputSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (flag);
|
||||
|
||||
//sleep(5);
|
||||
fclose(outputFile);
|
||||
|
||||
for (int i = 0; i < SLAVE_NUM; i++){
|
||||
if (wait(NULL) == -1)
|
||||
printSystemError("wait() -- ERROR");
|
||||
}
|
||||
|
||||
sigset_t set;
|
||||
sigaddset(&set, SIGUSR2);
|
||||
if (fclose(outputFile) == EOF)
|
||||
printSystemError("fclose() -- ERROR");
|
||||
|
||||
if (viewLinked) {
|
||||
int temp = 0;
|
||||
sigwait(&set, &temp);
|
||||
terminateShm("/BottlerSHM", shmFd, shmStart, (argc - 1) * MAX_OUTPUT_SIZE);
|
||||
waitForSignal();
|
||||
terminateShm(SHM_NAME, shmFd, shmStart, totalSize);
|
||||
closeSem();
|
||||
}
|
||||
|
||||
//close(shmFd);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -159,7 +120,8 @@ void changeViewFlag() {
|
|||
viewLinked = 1;
|
||||
}
|
||||
|
||||
char sendTask(struct stat statBuf, char * fileName, int pipesInput[SLAVE_NUM][2], int slave) {
|
||||
char sendTask(char * fileName, int pipesInput[slaveNum][2], int slave) {
|
||||
struct stat statBuf;
|
||||
if (stat(fileName, &statBuf) == -1)
|
||||
printSystemError("Error, one of the specified paths is incorrect");
|
||||
|
||||
|
@ -172,17 +134,19 @@ char sendTask(struct stat statBuf, char * fileName, int pipesInput[SLAVE_NUM][2]
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void closePipes(int pipesInput[SLAVE_NUM][2], int pipesOutput[SLAVE_NUM][2], int slave) {
|
||||
void closePipes(int pipesInput[][2], int pipesOutput[][2], int slave, fd_set * set) {
|
||||
// FD_CLR(pipesOutput[slave][0], set);
|
||||
|
||||
if (close(pipesOutput[slave][0]) < 0)
|
||||
printSystemError("close() -- ERROR");
|
||||
printSystemError("close1() -- ERROR");
|
||||
if (close(pipesInput[slave][1]) < 0)
|
||||
printSystemError("close() -- ERROR");
|
||||
printSystemError("close2() -- ERROR");
|
||||
|
||||
pipesOutput[slave][0] = -1;
|
||||
pipesInput[slave][0] = -1;
|
||||
}
|
||||
|
||||
int writeOutput(char * output, FILE * outputFile, void * shmPointer, char viewLinked) {
|
||||
int writeOutput(char * output, FILE * outputFile, char * shmPointer, int i) {
|
||||
int length = strlen(output);
|
||||
|
||||
if (fwrite(output, sizeof(char), length, outputFile) != length)
|
||||
|
@ -194,10 +158,10 @@ int writeOutput(char * output, FILE * outputFile, void * shmPointer, char viewLi
|
|||
return length;
|
||||
}
|
||||
|
||||
void createPipes(int pipesOutput[SLAVE_NUM][2], int pipesInput[SLAVE_NUM][2]) {
|
||||
pid_t pid[SLAVE_NUM];
|
||||
void createPipesAndSlaves(int pipesOutput[slaveNum][2], int pipesInput[slaveNum][2]) {
|
||||
pid_t pid[slaveNum];
|
||||
|
||||
for (int i = 0; i < SLAVE_NUM; i++) {
|
||||
for (int i = 0; i < slaveNum; i++) {
|
||||
if (pipe(pipesOutput[i]) < 0)
|
||||
printSystemError("pipe() -- ERROR");
|
||||
if (pipe(pipesInput[i]) < 0)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef MASTER_H
|
||||
#define MASTER_H
|
||||
|
||||
#define MAX_SLAVES 500
|
||||
#define MAX_SIZE 300
|
||||
#define MAX_PATH_SIZE 100
|
||||
#define MAX_OUTPUT_SIZE (200 + MAX_PATH_SIZE)
|
||||
#define OUTPUT_NAME "outputFile.txt"
|
||||
|
||||
void createPipesAndSlaves(int pipesOutput[][2], int pipesInput[][2]);
|
||||
int writeOutput(char * output, FILE * outputFile, char * shmPointers, int cacaDeEzequiel);
|
||||
void closePipes(int pipesInput[][2], int pipesOutput[][2], int slave, fd_set * set);
|
||||
char sendTask(char * fileName, int pipesInput[][2], int slave);
|
||||
void changeViewFlag();
|
||||
|
||||
#endif
|
78
shr_mem.c
78
shr_mem.c
|
@ -1,65 +1,71 @@
|
|||
/*
|
||||
This is a personal academic project. Dear PVS-Studio, please check it.
|
||||
PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
#define _SVID_SOURCE 1
|
||||
//#define _DEFAULT_SOURCE 1
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/shm.h>
|
||||
#include <semaphore.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "shr_mem.h"
|
||||
#include "error.h"
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "shr_mem.h"
|
||||
|
||||
sem_t * sem = NULL;
|
||||
|
||||
int createShm(int totalSize, void ** shmPointer) {
|
||||
int createShm(int totalSize) {
|
||||
int fd;
|
||||
if ((fd = shm_open("/BottlerSHM", O_CREAT | O_RDWR, S_IRWXU)) < 0)
|
||||
if ((fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRWXU)) < 0)
|
||||
printSystemError("shm_open() -- ERROR");
|
||||
ftruncate(fd, totalSize);
|
||||
//* shmPointer = mmap(0, totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int writeShm(void * shmPointer, char * str, int len) {
|
||||
if (sem == NULL) {
|
||||
if ((sem = sem_open("/EMPTY", O_CREAT | O_RDWR, S_IRWXU, 0)) == SEM_FAILED)
|
||||
printSystemError("sem_open() -- ERROR");
|
||||
}
|
||||
void mapShm(char ** shmPointer, int totalSize, int fd) {
|
||||
if ((* shmPointer = mmap(0, totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
|
||||
printSystemError("mmap() -- ERROR");
|
||||
}
|
||||
|
||||
void writeShm(char * shmPointer, char * str, int len) {
|
||||
openSem();
|
||||
|
||||
if (memcpy(shmPointer, str, len) == NULL)
|
||||
printError("memcpy() -- ERROR");
|
||||
|
||||
if (sem_post(sem) < 0)
|
||||
printSystemError("sem_post() -- ERROR");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void terminateShm(const char * name, int fd, void * shmPointer, int totalSize) {
|
||||
void terminateShm(const char * name, int fd, char * shmPointer, int totalSize) {
|
||||
if (munmap(shmPointer, totalSize) == -1)
|
||||
printSystemError("munmap() -- ERROR");
|
||||
if (shm_unlink(name) == -1)
|
||||
printSystemError("shm_unlink() -- ERROR");
|
||||
if (close(fd) == -1)
|
||||
printSystemError("close() -- ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
void openSem() {
|
||||
if (sem == NULL) {
|
||||
if ((sem = sem_open(SEM_NAME, O_CREAT | O_RDWR, S_IRWXU, 0)) == SEM_FAILED)
|
||||
printSystemError("sem_open() -- ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
void closeSem() {
|
||||
if (sem_close(sem) < 0)
|
||||
printSystemError("sem_close() -- ERROR");
|
||||
if (sem_unlink("/EMPTY") < 0)
|
||||
if (sem_unlink(SEM_NAME) < 0)
|
||||
printSystemError("sem_unlink() -- ERROR");
|
||||
}
|
||||
|
||||
int copyShm(char * destPointer, char * srcPointer, int len) {
|
||||
int i;
|
||||
//for (i = 0; srcPointer[i] != '\0' && i < len; i++) {
|
||||
for (i = 0; srcPointer[i] != '\n' && srcPointer[i] != '\0' && i < len; i++) {
|
||||
for (i = 0; i < len && srcPointer[i] != '\n' && srcPointer[i] != '\0'; i++) {
|
||||
destPointer[i] = srcPointer[i];
|
||||
}
|
||||
destPointer[i++] = '\0';
|
||||
|
@ -68,20 +74,28 @@ int copyShm(char * destPointer, char * srcPointer, int len) {
|
|||
}
|
||||
|
||||
int readShm(char * shmPointer, char * str, int len) {
|
||||
if (sem == NULL) {
|
||||
if ((sem = sem_open("/EMPTY", O_CREAT | O_RDWR, S_IRWXU, 0)) == SEM_FAILED)
|
||||
printSystemError("sem_open() -- ERROR");
|
||||
}
|
||||
openSem();
|
||||
|
||||
if (sem_wait(sem) < 0)
|
||||
printSystemError("sem_wait() -- ERROR");
|
||||
|
||||
int copied = copyShm(str, shmPointer, len);
|
||||
|
||||
// Creo que es lo mismo si hacemos:
|
||||
/*
|
||||
memcpy(str, shmPointer, len);
|
||||
*shmPointer += len;
|
||||
*/
|
||||
|
||||
return copied;
|
||||
return copyShm(str, shmPointer, len);
|
||||
}
|
||||
|
||||
int openCreatedShm(char ** shmPointer, int totalSize) {
|
||||
int fd;
|
||||
if ((fd = shm_open(SHM_NAME, O_RDONLY, S_IRUSR)) < 0)
|
||||
printSystemError("shm_open() -- ERROR");
|
||||
|
||||
if ((* shmPointer = mmap(0, totalSize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED){
|
||||
printSystemError("mmap() -- ERROR");
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void closeCreatedShm(char * shmPointer, int totalSize, int fd) {
|
||||
if (munmap(shmPointer, totalSize) == -1)
|
||||
printSystemError("munmap() -- ERROR");
|
||||
if (close(fd) < 0)
|
||||
printSystemError("close() -- ERROR");
|
||||
}
|
||||
|
|
14
shr_mem.h
14
shr_mem.h
|
@ -1,11 +1,17 @@
|
|||
#ifndef SHR_MEM
|
||||
#define SHR_MEM
|
||||
|
||||
int createShm();
|
||||
char * attachShm(int shmId);
|
||||
int writeShm(void * address, char * str, int len);
|
||||
#define SHM_NAME "/BottlerSHM"
|
||||
#define SEM_NAME "/EmptySEM"
|
||||
|
||||
int createShm(int totalSize);
|
||||
void mapShm(char ** shmPointer, int totalSize, int fd);
|
||||
void writeShm(char * address, char * str, int len);
|
||||
int readShm(char * address, char * str, int len);
|
||||
void terminateShm(const char * name, int fd, void * shmPointer, int totalSize);
|
||||
void terminateShm(const char * name, int fd, char * shmPointer, int totalSize);
|
||||
void openSem();
|
||||
void closeSem();
|
||||
int openCreatedShm(char ** shmPointer, int totalSize);
|
||||
void closeCreatedShm(char * shmPointer, int totalSize, int fd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
This is a personal academic project. Dear PVS-Studio, please check it.
|
||||
PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#include "siglib.h"
|
||||
#include <signal.h>
|
||||
#include "error.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void addSignalHandler(void (*changeViewFlag)()) {
|
||||
struct sigaction sigAct = {{0}};
|
||||
sigAct.sa_handler = changeViewFlag;
|
||||
sigAct.sa_flags = 0;
|
||||
|
||||
if (sigaction(SIGUSR1, &sigAct, NULL) == -1)
|
||||
printSystemError("sigaction() -- ERROR");
|
||||
}
|
||||
|
||||
// Podríamos de última hacer que devuelvan el sigset para no tener dos distintos...
|
||||
|
||||
void blockSignal() {
|
||||
sigset_t blockedSet = {{0}};
|
||||
sigaddset(&blockedSet, SIGUSR1);
|
||||
sigprocmask(SIG_BLOCK, &blockedSet, NULL);
|
||||
}
|
||||
|
||||
void waitForSignal() {
|
||||
sigset_t set;
|
||||
sigaddset(&set, SIGUSR2);
|
||||
int temp;
|
||||
sigwait(&set, &temp);
|
||||
}
|
||||
|
||||
void sendSignal(int pid, int sig) {
|
||||
union sigval value = {0};
|
||||
sigqueue(pid, sig, value);
|
||||
}
|
||||
|
||||
void sendStartSignal(int pid) {
|
||||
sendSignal(pid, SIGUSR1);
|
||||
}
|
||||
|
||||
void sendFinishSignal(int pid) {
|
||||
sendSignal(pid, SIGUSR2);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef SIGLIB_H
|
||||
#define SIGLIB_H
|
||||
|
||||
void addSignalHandler(void (*changeViewFlag)());
|
||||
void blockSignal();
|
||||
void waitForSignal();
|
||||
void sendStartSignal(int pid);
|
||||
void sendFinishSignal(int pid);
|
||||
|
||||
#endif
|
36
slave.c
36
slave.c
|
@ -5,9 +5,9 @@ PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|||
#define _POSIX_C_SOURCE 2
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "error.h"
|
||||
|
||||
#define MAX_SIZE 300
|
||||
|
@ -17,24 +17,16 @@ void runCommand(char *, char *);
|
|||
void printOutput(char *, char *);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
if (setvbuf(stdout, NULL, _IONBF, 0) != 0)
|
||||
printSystemError("setvbuf() -- ERROR");
|
||||
|
||||
char output[MAX_SIZE];
|
||||
char input[MAX_SIZE];
|
||||
|
||||
/*
|
||||
// Falta manejo de errores de fgets!
|
||||
while (fgets(input, MAX_SIZE, stdin)) {
|
||||
input[strcspn(input, "\n")] = '\0';
|
||||
runCommand(input, output);
|
||||
printOutput(output, input);
|
||||
}
|
||||
*/
|
||||
char output[MAX_SIZE], input[MAX_SIZE];
|
||||
|
||||
int readChars;
|
||||
while ((readChars = read(STDIN_FILENO, input, MAX_SIZE) != 0)) {
|
||||
while ((readChars = read(STDIN_FILENO, input, MAX_SIZE)) != 0) {
|
||||
if (readChars < 0)
|
||||
printSystemError("slave.c -- read()");
|
||||
input[readChars] = '\0';
|
||||
|
||||
char * inputLine = strtok(input, "\n");
|
||||
while (inputLine != NULL) {
|
||||
|
@ -44,21 +36,17 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// int saved_flags = fcntl(fd, F_GETFL);
|
||||
// fcntl(fd, F_SETFL, saved_flags & ~O_NONBLOCK);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void runCommand(char * inputLine, char * output) {
|
||||
char command[COMMAND_MAX_SIZE];
|
||||
//sprintf(command, "minisat %s | grep -o -e \"Number of .*[0-9]\\+\" -e \"CPU time.*\" -e \".*SATISFIABLE\" | awk '{if (NR == 1) {print $4} ; if (NR == 2) {print $4} ; if (NR == 3) {print $4 $5} ; if (NR == 4) {print $1}}'", inputLine);
|
||||
sprintf(command, "minisat %s | grep -o -e \"Number of .*[0-9]\\+\" -e \"CPU time.*\" -e \".*SATISFIABLE\" | awk '{if (NR == 1) {printf \"Cantidad de variables: \" $4 \" - \"} ; if (NR == 2) {printf \"Cantidad de cláusulas: \" $4 \" - \"} ; if (NR == 3) {printf \"Tiempo de procesamiento: \" $4 $5 \" - \"} ; if (NR == 4) {printf \"Resultado: \" $1}}'", inputLine);
|
||||
sprintf(command, "minisat %s | grep -o -e \"Number of .*[0-9]\\+\" -e \"CPU time.*\" -e \".*SATISFIABLE\" | awk '{if (NR == 1) {printf \"Cantidad de variables: \" $4 \" - \"} ; if (NR == 2) {printf \"Cantidad de clausulas: \" $4 \" - \"} ; if (NR == 3) {printf \"Tiempo de procesamiento: \" $4 $5 \" - \"} ; if (NR == 4) {printf \"Resultado: \" $1}}'", inputLine);
|
||||
// Pequeña ayuda para popen: https://stackoverflow.com/questions/646241/c-run-a-system-command-and-get-output
|
||||
FILE * fp;
|
||||
if (!(fp = popen(command, "r")))
|
||||
FILE * fp = popen(command, "r");
|
||||
if (fp == NULL)
|
||||
printSystemError("slave.c -- popen()");
|
||||
|
||||
// Ver manejo de errores de fread!
|
||||
size_t outputLength = fread(output, sizeof(char), MAX_SIZE, fp);
|
||||
output[outputLength] = '\0';
|
||||
|
||||
|
@ -67,12 +55,8 @@ void runCommand(char * inputLine, char * output) {
|
|||
|
||||
if (pclose(fp) < 0)
|
||||
printSystemError("slave.c -- pclose()");
|
||||
|
||||
}
|
||||
|
||||
void printOutput(char * output, char * fileName) {
|
||||
printf("Nombre del archivo: %s - %s - Id del esclavo: %d\n", fileName, output, getpid());
|
||||
|
||||
// int saved_flags = fcntl(fd, F_GETFL);
|
||||
// fcntl(fd, F_SETFL, saved_flags & O_NONBLOCK);
|
||||
}
|
56
view.c
56
view.c
|
@ -1,16 +1,15 @@
|
|||
/*
|
||||
This is a personal academic project. Dear PVS-Studio, please check it.
|
||||
PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "error.h"
|
||||
#include "shr_mem.h"
|
||||
#include <semaphore.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include "siglib.h"
|
||||
|
||||
#define MAX_SIZE 300
|
||||
#define MAX_AMOUNT_SIZE 10
|
||||
|
@ -19,8 +18,8 @@
|
|||
#define MAX_OUTPUT_SIZE (200 + MAX_PATH_SIZE)
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
char amount[MAX_AMOUNT_SIZE];
|
||||
char masterPid[MAX_PID_SIZE];
|
||||
char amount[MAX_AMOUNT_SIZE] = {0};
|
||||
char masterPid[MAX_PID_SIZE] = {0};
|
||||
switch (argc) {
|
||||
case 1:
|
||||
fgets(amount, MAX_AMOUNT_SIZE, stdin);
|
||||
|
@ -29,53 +28,34 @@ int main(int argc, char * argv[]) {
|
|||
masterPid[strcspn(masterPid, "\n")] = '\0';
|
||||
break;
|
||||
case 3:
|
||||
strcpy(amount, argv[1]);
|
||||
strcpy(masterPid, argv[2]);
|
||||
strncpy(amount, argv[1], MAX_AMOUNT_SIZE - 1);
|
||||
strncpy(masterPid, argv[2], MAX_PID_SIZE - 1);
|
||||
amount[MAX_AMOUNT_SIZE - 1] = '\0';
|
||||
masterPid[MAX_PID_SIZE - 1] = '\0';
|
||||
break;
|
||||
default:
|
||||
printError("View must receive amount of files and the pid of master process by argument or stdin");
|
||||
printError("View must receive amount of files and the pid of master process by argument or stdin -- ERROR");
|
||||
}
|
||||
|
||||
int files = atoi(amount);
|
||||
int mPid = atoi(masterPid);
|
||||
printf("%d\n", files);
|
||||
printf("%d\n", mPid);
|
||||
|
||||
union sigval value;
|
||||
sigqueue(mPid, SIGUSR1, value);
|
||||
|
||||
//sleep(2);
|
||||
|
||||
int fd;
|
||||
char * shmPointer;
|
||||
|
||||
if ((fd = shm_open("/BottlerSHM", O_RDONLY, S_IRUSR)) < 0)
|
||||
printSystemError("shm_open() -- ERROR");
|
||||
sendStartSignal(mPid);
|
||||
|
||||
int totalSize = files * MAX_OUTPUT_SIZE;
|
||||
|
||||
if ((shmPointer = mmap(0, totalSize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED){
|
||||
printSystemError("mmap() -- ERROR");
|
||||
}
|
||||
void * shmStart;
|
||||
char * shmPointer, * shmStart;
|
||||
int fd = openCreatedShm(&shmPointer, totalSize);
|
||||
shmStart = shmPointer;
|
||||
|
||||
int i = 0;
|
||||
char buf[MAX_SIZE];
|
||||
while (files-- > 0) {
|
||||
//buf[0] = '\0';
|
||||
shmPointer += readShm(shmPointer, buf, MAX_SIZE);
|
||||
printf("%d\t", i++);
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
if (munmap(shmStart, totalSize) == -1)
|
||||
printSystemError("munmap() -- ERROR");
|
||||
|
||||
close(fd);
|
||||
// terminateShm("/BottlerSHM", fd, shmStart, totalSize);
|
||||
|
||||
sigqueue(mPid, SIGUSR2, value);
|
||||
closeCreatedShm(shmStart, totalSize, fd);
|
||||
sendFinishSignal(mPid);
|
||||
closeSem();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue