I'm trying to use child processes in my quicksort, such that the left half sorts in one child and the right half in another child. I had it working prior to the shmget implementation but now I believe I'm corrupting the array somewhere because all my values become zero after printing the array. Sorry if I'm making some dumb mistake somewhere, I'm trying to learn how to use fork and shmget but have been running into some trouble. I'm trying to take in a text file as a command line argument and given a delimiter such as ';' I have to remove the delimiter and identify the numbers in between, place them in an array and sort them using child processes. I have the parsing working, and the quicksort worked but now that I'm trying to implement the shared memory I've ran into some problems.
Thanks
I've looked at a few different examples, but the one that this is mostly based off is the geeksforgeeks example with mergesorting with fork. https://www.geeksforgeeks.org/concurrent-merge-sort-in-shared-memory/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "fileParser.h"
#include "dataManagement.h"
int main(int argc, char *argv[]){
char *file = argv[1];
char delimiter = argv[2][0];
MyArray *theArray = getArray(file, delimiter);
size_t SHM_SIZE = theArray->length;
theArray->key = IPC_PRIVATE;
if((theArray->shmid = shmget(theArray->key, SHM_SIZE, IPC_CREAT | 0666)) < 0){
perror("shmget");
_exit(-1);
}
if ((theArray->shm_array = shmat(theArray->shmid, NULL, 0)) == (int *) -1)
{
perror("shmat");
_exit(1);
}
printArray(theArray, theArray->length);
quickSortFork(theArray, 0, theArray->length-1);
printArray(theArray, theArray->length);
if (shmdt(theArray->shm_array) == -1)
{
perror("shmdt");
_exit(1);
}
if (shmctl(theArray->shmid, IPC_RMID, NULL) == -1)
{
perror("shmctl");
_exit(1);
}
return 0;
}
dataManagement.h
#include <unistd.h>
#include <sys/wait.h>
#include "fileParser.h"
int partition(MyArray *arr, int low, int high);
void quickSortFork(MyArray *arr, int low, int high);
void swap(MyArray *arr, int a, int b);
void printArray(MyArray *arr, int length) {
for(int i = 0; i < length; i++){
printf("%d ", arr->shm_array[i]);
}
printf("\n");
}
void quickSortFork(MyArray *arr, int low, int high){
pid_t lpid, rpid;
rpid = fork();
if(low < high){
int partitionIndex = partition(arr,low, high);
if(rpid < 0){
perror("Right child not created.\n");
exit(-1);
} else if(rpid == 0 ){
printf("I am the right child!\tMy process id: %d\n",getpid());
quickSortFork(arr, partitionIndex + 1, high);
exit(EXIT_SUCCESS);
} else {
lpid = fork();
if(lpid < 0){
perror("Left child not created.\n");
} else if (lpid == 0) {
quickSortFork(arr, low, partitionIndex - 1);
printf("I am the left child!\tMy process id: %d\n", getpid());
exit(EXIT_SUCCESS);
}
}
int status;
waitpid(rpid, &status, 0);
waitpid(lpid, &status, 0);
}
}
int partition(MyArray *arr, int low, int high){
int i = low, j = high;
int pivot = arr->shm_array[(low+high)/2];
while(i < j){
while(arr->shm_array[i] < pivot)
i++;
while(arr->shm_array[j] > pivot)
j--;
if(i < j){
swap(arr,i,j);
}
}
return i;
}
void swap(MyArray *arr, int a, int b){
int temp = arr->shm_array[a];
arr->shm_array[a] = arr->shm_array[b];
arr->shm_array[b] = temp;
}
fileParser.h
int findFileLength(FILE *inFile, char delimiter);
int *parseFileToArray(FILE *inFile, char delimiter, int length);
typedef struct {
int shmid;
key_t key;
int length;
int *shm_array;
} MyArray;
MyArray *getArray(char *fileName, char delimiter){
FILE *numberFile = fopen(fileName, "r"); // open for reading
if (numberFile == NULL) // unable to open file
return NULL;
MyArray *array = malloc(sizeof(MyArray));
array->length = findFileLength(numberFile, delimiter);
array->shm_array = parseFileToArray(numberFile, delimiter,array->length);
return array;
}
int findFileLength(FILE *inFile, char delimiter){
char c;
int length = 0;
c = fgetc(inFile);
while(c != EOF){
if(c != delimiter && c != '\n'){
length++;
while((c = fgetc(inFile)) != EOF && c != '\n' && c != delimiter);
} else {
c = fgetc(inFile);
}
}
rewind(inFile); // resets the file pointer to the start
return length;
}
int *parseFileToArray(FILE *inFile, char delimiter, int length){
int *parsedFile = malloc(sizeof(int) * length);
char c;
char *stringInt = malloc(sizeof(char) * 100); // string that is used to combine multiple characters and convert to an integer
int stringIntP = 0, parsedArrayP = 0; // pointers for our arrays, the first is for the string that determines the integer, the second is for our resulting array
c = fgetc(inFile);
while(c != EOF){
if(c != delimiter && c != '\n'){
for(;c != '\n' && c != delimiter; (c = fgetc(inFile)) != EOF){
stringInt[stringIntP++] = c;
}
stringIntP = 0;
parsedFile[parsedArrayP++] = atoi(stringInt); // convert string number to integer value
memset(stringInt, 0, 100); // clear the string that builds the integer value from chars
} else {
c = fgetc(inFile);
}
}
for(int i = 0; i < length; i++){
printf("%d ", parsedFile[i]);
}
printf("\n");
fclose(inFile); // close the file after using
free(stringInt);
return parsedFile;
}
Expected output: the array passed in unsorted first. Then the array sorted.
Actual output: array filled with 0's and program doesn't finish executing