d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > Make Me A Better Programmer - From Step 1
Prev1303132333456Next
Add Reply New Topic New Poll
Member
Posts: 23,862
Joined: Aug 16 2006
Gold: 20.00
Feb 24 2014 10:18pm
coord.c - The parent program

Code
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <wait.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include "helper.h"

//GLOBALLY DEFINED VARIABLES (explained in README)

int *A_SHARE;
int *B_SHARE;
int *C_SHARE;
struct shminfo *info;
pid_t *pids;
int INFO_ID, n;

int matSize(FILE *file, struct shminfo *info, int flag);
int getShm(int size);
void processLimit(int *p, FILE *f);
void handler(int sig);
void cleanUp(int *A_SHARE, int *B_SHARE, int *C_SHARE, int *flags, int INFO_ID, struct shminfo *info, pid_t *pids);

int main(int argc, char *argv[]) {
int k, j, size, opt, compTime, c_id = 0, totalProcess = 0;
char arg1[10];
char arg2[10];
char arg3[10];
char arg4[10];
FILE *f, *p;

//Catch signals INT and ALRM for handling

signal(SIGALRM, handler);
signal(SIGINT, handler);
signal(SIGQUIT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGABRT, SIG_IGN);

//Seed the random num generator (for use later when trying to seed sleep() inside of worker processes.

srand(time(NULL));

//Set default computation time

compTime = 100;

while ((opt = getopt (argc, argv, "ht:")) != -1) {
switch(opt) {
case 'h':
printf("Proper usage: coord [-t:] [Matrix A] [Matrix B] [Matrix C]\n");
printf("Please use the format for matricies A and B specified in the README\n");
exit(0);
case 't':
compTime = atoi(optarg);
break;
default:
break;
}
}

//Create various shared memory segments for the matricies, attach them and store their IDs

INFO_ID = shmget( IPC_PRIVATE, sizeof(struct shminfo), IPC_CREAT | IPC_EXCL | 0777);
if ( INFO_ID == -1 ) {
perror("coord: Error");
exit(1);
}

//Attach ID for our information struct

info = (struct shminfo *)shmat(INFO_ID, 0, 0);

f = fopen(argv[optind], "r");
size = matSize(f, info, 0);

info->A_ID = getShm(size);
A_SHARE = (int *)shmat(info->A_ID, 0, 0);

for (k = 0; k < size; k++) {
fscanf(f, "%d", &A_SHARE[k]);
}

f = fopen(argv[optind + 1], "r");
size = matSize(f, info, 1);

info->B_ID = getShm(size);
B_SHARE = (int *)shmat(info->B_ID, 0, 0);

for (k = 0; k < size; k++) {
fscanf(f, "%d", &B_SHARE[k]);
}

info->FLAGS_ID = shmget( IPC_PRIVATE, info->A_COLS * info->B_ROWS * sizeof(int), IPC_CREAT | IPC_EXCL | 0777);
if ( info->FLAGS_ID == -1 ) {
perror("coord: Error");
exit(1);
}

n = info->A_ROWS * info-> B_COLS;

//Set up our final (result) matrix: Set up shared mem, attach and open the file argument

info->C_ID = getShm(n);
C_SHARE = (int *)shmat(info->C_ID, 0, 0);
info->C_ROWS = info->A_ROWS;
info->C_COLS = info->B_COLS;

flags = (int *)shmat(info->FLAGS_ID, 0, 0);

f = fopen(argv[optind + 2], "w");

sprintf(arg1, "%d", INFO_ID);

pids = (pid_t *)malloc(n * sizeof(pid_t));

//Open (possibly create) Log file for recording

p = fopen("Log", "w+");

//Set our computation time alarm

alarm(compTime);

//Nested loop structure to produce children

for (k = 0; k < info->A_ROWS; k++) {
for (j = 0; j < info->B_COLS; j++) {

//Convert various integer args to strings for the sake of passing in EXECL

sprintf(arg2, "%d", k);
sprintf(arg3, "%d", j);
sprintf(arg4, "%d", c_id);

++totalProcess;

if ((pids[c_id] = fork() ) < 0) {
perror("coord: Error");
return 1;
}

//If process is child, exec it into the worker program

if (pids[c_id] == 0) {

// Try to get a better random seed from time() in worker processes

usleep(5 * (rand() % 3)); //
execl("worker", "worker", arg1, arg2, arg3, arg4, (char *)(NULL));
}

++c_id;

if (totalProcess >= 20) {
processLimit(&totalProcess, p);
}
}
}

//The loop above works in blocks of 20; check to see if any processes are still finishing

if (totalProcess > 0) {
processLimit(&totalProcess, p);
}

//Write our result matrix C to the file specified in argv

for (k = 0; k < n; k++) {
if (k % info->C_COLS == 0 && k != 0) {
fprintf(f, "\n");
}
fprintf(f, "%d ", C_SHARE[k]);
}

//Clean up any shared memory and other things left lying around

cleanUp(A_SHARE, B_SHARE, C_SHARE, flags, INFO_ID, info, pids);

return 0;
}

//Function for handling interrupts

void handler(int sig) {
if (sig == SIGINT) {
printf("\nSIGINT recieved: cleaning up and terminating child processes...\n");
}
if (sig == SIGALRM) {
printf("\nComputation has gone over alotted time limit: cleaning up and terminating child processes...\n");
}
int k;
for (k = 0; k < n; k++) {
if (pids[k] > 0) {
kill(pids[k], SIGTERM);
}
}
cleanUp(A_SHARE, B_SHARE, C_SHARE, flags, INFO_ID, info, pids);
exit(1);
}

//Function for cleaning up memory

void cleanUp(int *A_SHARE, int *B_SHARE, int *C_SHARE, int *flags, int INFO_ID, struct shminfo *info, pid_t *pids) {

shmdt( (void *) A_SHARE );
shmdt( (void *) B_SHARE );
shmdt( (void *) C_SHARE );
shmdt( (void *) flags );

shmctl(info->A_ID, IPC_RMID, 0);
shmctl(info->B_ID, IPC_RMID, 0);
shmctl(info->C_ID, IPC_RMID, 0);
shmctl(info->FLAGS_ID, IPC_RMID, 0);

shmdt( (void *) info );
shmctl(INFO_ID, IPC_RMID, 0);

free(pids);
}

//Function to wait for children to finish & write their results to the log file

void processLimit(int *p, FILE *f) {
int k = *p;
int status;
pid_t pid;

while (k > 0) {
pid = wait (&status);

f=fopen("Log", "ab+");
fprintf(f, "coord: Child %ld returned result %d\n", (long)pid, WEXITSTATUS(status));

--k;
--*p;
}
}

//Function to get the total size n of a matrix, where n = rows * columns

int matSize(FILE *file, struct shminfo *info, int flag) {
int rows = 0;
int cols = 0;
int prod = 0;

fscanf(file, "%d", &rows);
fscanf(file, "%d", &cols);

if (flag == 0) {
info->A_ROWS = rows;
info->A_COLS = cols;
} else {
info->B_ROWS = rows;
info->B_COLS = cols;
}

prod = rows * cols;

return prod;
}

// Function to get shared memory IDs

int getShm(int size) {
int memId;

memId = shmget( IPC_PRIVATE, size*sizeof(int), IPC_CREAT | IPC_EXCL | 0777);
if ( memId == -1 ) {
perror("coord: Error");
exit(1);
}

return memId;;
}


worker.c - The Child program

Code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "helper.h"

void process(const int i, int n, int *flag, struct shminfo *info);
void critical(long times, int id);

int ele;

int main(int argc, char *argv[]) {
int *A_MAT, *B_MAT, *C_MAT;
int i, row, col, num, processID;
int element = 0;
int infoID;
int *flag;
struct shminfo *info;

infoID = atoi(argv[1]);
row = atoi(argv[2]);
col = atoi(argv[3]);
processID = atoi(argv[4]);

info = (struct shminfo *)shmat(infoID, 0, 0);

A_MAT = (int *)shmat(info->A_ID, 0, 0);
B_MAT = (int *)shmat(info->B_ID, 0, 0);
C_MAT = (int *)shmat(info->C_ID, 0, 0);
flag = (int *)shmat(info->FLAGS_ID, 0, 0);

num = info->A_ROWS * info->B_COLS;

//TODO: Fix larger x smaller matrix

for (i = 0; i < info->A_COLS; i++) {
element += A_MAT[(row * info->A_COLS) + i] * B_MAT[(i * info->A_ROWS) + col];
}

ele = element;

C_MAT[(info->C_ROWS * row) + col] = element;

printf("Worker ID %d (PID: %d) produced result %d from operands %d and %d\n", processID, (int)getpid(), element, row, col);

process(processID, num, flag, info);

return element;
}

void process(const int i, int n, int *flag, struct shminfo *info) {
int j;
long times = 0;

do {

flag[i] = want_in;
j = info->turn;

while(j != i) {
j = (flag[j] != idle) ? info->turn : (j + 1) % n;
}

flag[i] = in_cs;

for (j = 0; j < n; j++) {
if ((j != i) && (flag[j] == in_cs)) {
break;
}
}
times++;
} while ((j < n) || (info->turn != i && flag[info->turn] != idle));

info->turn = i;

critical(times, i);

j = (info->turn + 1) % n;
while (flag[j] == idle) {
j = (j + 1) % n;
}

info->turn = j;
flag[i] = idle;

}

void critical(long times, int id) {
time_t currentTime;
int cid;

cid = getpid();

srand(time(NULL));

sleep(rand() % 3 + 1);

FILE *f;

f = fopen("Log", "a+");
time(&currentTime);

fprintf(f, "Child %d attempted to enter critical section %ld times\n", cid, times);
fprintf(f, "Child %d wrote value %d to the matrix\n", cid, ele);
fprintf(f, "Child %d exited critical section at %s\n", cid, ctime(&currentTime));

}
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Feb 25 2014 04:31am
You should be initializing all your variables, especially pointers (to null), to some value when you create them. It doesn't take you any more time and it's better practice. Also if you set a pointer to null and you accidentally use it in a standard C function most of the time the function will just return null or 0 where as if you used a uninitialized pointer (which may be pointing anywhere in memory when it is first created) it could cause seg faults and other nastiness if you forget to use them the right way.

This post was edited by AbDuCt on Feb 25 2014 04:32am
Member
Posts: 23,862
Joined: Aug 16 2006
Gold: 20.00
Feb 25 2014 12:36pm
Quote (AbDuCt @ Feb 25 2014 05:31am)
You should be initializing all your variables, especially pointers (to null), to some value when you create them. It doesn't take you any more time and it's better practice. Also if you set a pointer to null and you accidentally use it in a standard C function most of the time the function will just return null or 0 where as if you used a uninitialized pointer (which may be pointing anywhere in memory when it is first created) it could cause seg faults and other nastiness if you forget to use them the right way.


Yeah, half way through I was having some problems because I didn't initialize certain variables.

Trying to access index (-41432543) of an array is always fun.

Good point, something I need to remember more often.

edit:

Another thing that worried me was file streams.

I did a terrible job handling the file streams (with regards to closing them) and it wasn't until after I submitted that I spent some time thinking about it.

I was initially worried about using fclose() in the child programs since they were running concurrently. However, since I did all the file stuff INSIDE the critical section, it should not have been a problem.

In coord (the parent program), I forgot to close the streams as well.

That was one that bothered me and something I could have remedied with some more testing. Instead, I let the kernel handle my problems. (And I specifically used SIGTERM for killing the children because I wanted them to be cleaned up as well)

edit 2: I know that shit doesn't fly anywhere (leaving shit open) so I feel extra bad for doing it.

This post was edited by Eep on Feb 25 2014 12:44pm
Member
Posts: 23,862
Joined: Aug 16 2006
Gold: 20.00
Feb 26 2014 10:18pm
got the highest grade in my class on the first exam (aka the hell exam)

feeling not too bad

also got a 95/100 on the last assignment I posted

next one is about using semaphores....oh boy
Member
Posts: 11,610
Joined: Oct 28 2008
Gold: 1,795.00
Feb 27 2014 09:15am
Isn't there something similar to

with open(file.name, w)
Params


For C? Never have to worry about closing files when you're done and it looks cleaner IMO
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Feb 27 2014 01:45pm
Quote (0n35 @ Feb 27 2014 11:15am)
Isn't there something similar to

with open(file.name, w)
    Params


For C? Never have to worry about closing files when you're done and it looks cleaner IMO


This is why you're a php programmer.
Member
Posts: 11,610
Joined: Oct 28 2008
Gold: 1,795.00
Feb 27 2014 07:12pm
Quote (AbDuCt @ Feb 27 2014 01:45pm)
This is why you're a php programmer.


This isn't something you can do in php to my knowledge.

Please message me on Skype for more help with php since it's so bad.

This post was edited by 0n35 on Feb 27 2014 07:12pm
Member
Posts: 13,425
Joined: Sep 29 2007
Gold: 0.00
Warn: 20%
Feb 27 2014 09:36pm
Quote (0n35 @ Feb 27 2014 09:12pm)
This isn't something you can do in php to my knowledge.

Please message me on Skype for more help with php since it's so bad.


Asked you to do up some html templates. The entire php backend was my doing because php is bad. Get it right <3

This post was edited by AbDuCt on Feb 27 2014 09:37pm
Member
Posts: 11,610
Joined: Oct 28 2008
Gold: 1,795.00
Feb 28 2014 09:07am
Claim ruby is a god send

Still uses php

http://i.imgur.com/MTrxNlI.png
Member
Posts: 1,241
Joined: Jun 25 2011
Gold: Locked
Feb 28 2014 09:43am
Quote (Eep @ Feb 27 2014 06:18am)
got the highest grade in my class on the first exam (aka the hell exam)

feeling not too bad

also got a 95/100 on the last assignment I posted

next one is about using semaphores....oh boy


its actually farily easy once you've understood it properly :P
Go Back To Programming & Development Topic List
Prev1303132333456Next
Add Reply New Topic New Poll