Я пытаюсь определить, существует ли элемент в векторе, используя N процессов, и если true, вернуть все его позиции. Каждый процесс получает индекс и шаг. Индекс имеет значение от 0 до «numberOFProcesses -1», и каждый элемент проверки процесса, начиная с индекса, увеличивается с шагом.
Как это работает: Предположим, у нас есть 4 процесса. Процесс 0 проверяет элементы 0,4,8 ..., процесс 1 проверяет 1,5,9 ... и т. Д.
Как я это реализовал: Я получил 2 трубы: одна труба используется для позиций; второй канал для хранения количества вхождений цели. Всякий раз, когда процесс находит цель, он увеличивает число вхождений и записывает индекс в канал " index " и, наконец, после выхода из задания он записывает в " вхождения " канал количество вхождений, если таковые имеются, и возвращают истину или ложь. Первоначально я хотел напрямую вернуть количество вхождений, но понял, что «WEXITSTATUS» использует только 8 битов, и это может быть проблемой.
Проблема: Попытка чтения фрагмента «вхождений» не удалась или выдает недопустимые результаты. Кажется, что чтение значения за раз работает нормально. Я также проверил это, используя valgrind и gdb, но я не могу найти проблему. Valgrind сообщает о множестве проблем при попытке чтения чанка, но 0 ошибок при чтении по одному. Чтение вхождений выполняется только , если процесс нашел цель.
P.S. Я знаю, что могу оставить это так, но не будет смысла читать несколько раз.
Теперь для некоторого кода:
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <sys/signal.h>
#include <sys/types.h>
/**
* @brief basic defines
*
*/
#define MAX_RAND 100
#define TRUE 1
#define FALSE 0
#define CHILDREN 0
#define READ 0
#define WRITE 1
int size = 13;
int *array;
int target;
int index_pipe[2];
int occurences_pipe[2];
/**
* @brief this populates the array with random number
*
* @param array the given array
* @param size the size of the array
*/
void populate(int *array, int size)
{
for (int i = 0; i < size; i++)
{
array[i] = rand() % MAX_RAND;
}
}
/**
* @brief this determines whether an elements occurs in an array and writes to pipes the number
* of occurences and the the indexes on which resides the target
*
* @param target the value we are looking for
* @param index the index of the process, i.e. the process id
* @param step the step, i.e. the number of processes
* @return int the search status. This returns true if "target occurs", FALSE otherwise
*/
int search(int target, int index, int step)
{
int i = index;
int numberOfOccurences = 0;
/**
* @brief each process will start at position index and will check values starting with index, incrementing with step
* ex: process 0 will check 0,4,8,12..
* process 1 will check 1,5,9,13...
*/
while (i < size)
{
if (target == array[i])
{
/**
* @brief if the target occues increment the number of occurences and write an index to pipe
*
*/
numberOfOccurences++;
write(index_pipe[WRITE], &i, sizeof(int));
}
i += step;
}
/**
* @brief write occurences to pipe if, and only if, the number of occurences is not 0,
* i.e. we have found the target at least once and return TRUE or FALSE
*
*/
if (numberOfOccurences != 0)
{
write(occurences_pipe[WRITE], &numberOfOccurences, sizeof(int));
return TRUE;
}
return FALSE;
}
/**
* @brief this prints a given array
*
* @param array the array we want to print
* @param size the size of the array
*/
void printArray(int *array, int size)
{
printf("Array: \n");
for (int i = 0; i < size; i++)
{
printf("%d ", array[i]);
}
printf("\n");
}
/**
* @brief entry point
*
* @return int EXIT_SUCCESS
*/
int main()
{
/**
* @brief initialize and allocate memory
*
*/
size = 13;
array = (int *)malloc(sizeof(int) * size);
pipe(index_pipe);
pipe(occurences_pipe);
int numerOfProccesses = 3;
int target = 15;
int totalOccurences = 0;
int status = -1;
int exit_status = -1;
int occurences = -1;
populate(array, size);
array[size - 1] = target;
printArray(array, size);
size_t processes[numerOfProccesses];
/**
* @brief create childrens and put them to work
*
*/
for (int i = 0; i < numerOfProccesses; i++)
{
processes[i] = fork();
if (CHILDREN == processes[i])
{
/**
* @brief get the search status and exit
*
*/
int exit_status = search(target, i, numerOfProccesses);
exit(exit_status);
}
}
/**
* @brief wait for children to exit
*
*/
for (int i = 0; i < numerOfProccesses; i++)
{
/**
* @brief wait for each children. If a children is done AND it has found taget, i.e. returned TRUE,
* then read the number of occurrences from pipe
*
*/
wait(&status);
if (WIFEXITED(status))
{
exit_status = WEXITSTATUS(status);
if (exit_status == TRUE)
{
read(occurences_pipe[READ], &occurences, sizeof(int));
totalOccurences += occurences;
}
}
}
/**
* @brief if the number of occurrences is 0, then we have'nt found target
*
*/
if (totalOccurences == 0)
{
printf("%d not found \n", target);
}
else
{
/**
* @brief else allocate memory for an array of size "occurrences" and read from index pipe
*
*/
printf("Found %d on %d positions\n", target, totalOccurences);
int *indexes = (int *)malloc(sizeof(int) * 3);
// for (int i = 0; i < totalOccurences; i++)
// {
// int value;
// read(index_pipe[READ], &value, sizeof(int));
// printf("Read %d \n", value);
// }
int pipe_status;
pipe_status = read(index_pipe[READ], indexes, totalOccurences);
printf("Pipe read %d bytes\n", pipe_status);
printArray(indexes, totalOccurences);
}
return 0;
}
Ожидаемый результат:
Array:
83 86 77 15 93 35 86 92 49 21 62 27 15
Found 15 on 2 positions
Read 3
Read 12
Array:
3 12
Я получаю это при чтении чанка за раз:
Array:
83 86 77 15 93 35 86 92 49 21 62 27 15
Found 15 on 2 positions
Pipe read 2 bytes
Array:
3 0
P.S. Я написал это на машине Linux. Я скомпилировал это с помощью: gcc -g -o search search.c -Wextra