I have 3 files — SwimMill.c
, Fish.c
, and Pellets.c
— each of which is compiled into an executable. When SwimMill
is run, it uses fork()
and exec()
to run Fish
and Pellets
. However, for some reason, when I use the terminal, compile the programs with make
, and run SwimMill
, the file Fish
runs first. Can anybody help me?
Makefile
all: SwimMill Fish Pellets
SwimMill: SwimMill.c
gcc -o SwimMill SwimMill.c
Fish: Fish.c
gcc -o Fish Fish.c -lm
Pellets: Pellets.c
gcc -o Pellets Pellets.c
SwimMill.c
// Uses both fish and pellets, 30 seconds, then print it out
// Create pellets at random intervals, from 0x80
// Eating --> Get rid of most significant bit
// Use shared memory for fish and pellet position only
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define SHM_SIZE 1000
/*
TODO: SwimMIll FIRST, draw and get everything working
*/
/* 1. Create share memory using shmget
2. Attach to shared memory using shmat
3. Do operations
4. Detach using shmdt
*/
void printGrid(int*);
void handler(int);
int main(int argc, char* argv[]) {
printf("Hello");
signal(SIGINT, handler);
key_t key;
int shmid;
int *shm;
int timer = 0;
int fish = 0;
int pellet[20];
key = ftok("SwimMill.c", 'b'); //generate random ke
shmid = shmget(key, SHM_SIZE, IPC_CREAT|0666);
shm = shmat(shmid, NULL, 0); // Attach
// Initializing the shared memory to prevent segmentation fault
for (int i = 0; i < SHM_SIZE; i++){
shm[i] = -1;
}
int index = 0;
while(timer <= 30){
sleep(1); // Slow process down
fish = fork();
execv("Fish", argv);
pellet[index] = fork();
execv("Pellets", argv);
printGrid(shm);
printf("\n");
timer++;
index++;
}
shmdt(shm);
shmctl(shmid, IPC_RMID, NULL);
printf("Program finished! \n");
getchar(); // Pause consol
return 0;
}
void printGrid(int* shm) {
int row = 10;
int column = 10;
char stream[row][column]; //2D Dimensional array, fish can only move last row of 2d
//Initializing grid first
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
stream[i][j] = '~';
}
}
//Printing out grid with fish and pellet
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
stream[i][j] = '~'; // water
for (int k = 0; k < 20; k++) {
stream[shm[k]/10][shm[k]%10] = 'O'; // pellets
stream[shm[0]/10][shm[0]%10] = 'Y'; // Fish
}
printf("%c ", stream[i][j] );
}
printf("\n");
}
}
void handler(int num) {
perror(" Interrupt signal is pressed!! \n");
exit(1);
}
Fish.c
// 1 fish
// Scan the entire array, and focus on one pellet
// Arrange itself
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <math.h>
#include <unistd.h>
int findClosestPellet(int*);
void moveLeft(int, int*);
void moveRight(int, int*);
int main() {
printf("printing from fish");
key_t key = ftok("SwimMill.c", 'b');
int shmid = shmget(key, 1024, IPC_CREAT|0666);
int *shm = (int*) shmat(shmid, NULL, 0);
int fish = 94; // Middle position
shm[0] = fish; // Store first shared memor space to fish
int columnToMoveTo = 0;
while(1) {
int closestPellet = shm[findClosestPellet(shm)];
if ((closestPellet % 10) > (fish % 10) ) {
moveRight(fish, shm);
}
else if ((closestPellet % 10) < (fish % 10)) {
moveLeft(fish, shm);
}
sleep(1);
}
shmdt(shm);
return 0;
}
int findClosestPellet(int* shm) {
// Using distance formula to find closest pellet
// (x2 - x1)^2 + (y2 - y1)^2
int closestPellet = 0;
int distance[20] = {0}; // Distance of all 20 pellets
int minimumDistance = 0;
// shm[1] = 11;
// shm[2] = 14;
// shm[3] = 10;
// shm[4] = 55;
int x2 = shm[0] % 10;
int y2 = shm[0] / 10;
for (int i = 1; i < 20; i++) {
int x1 = shm[i] % 10;
int y1 = shm[i] / 10;
distance[i] = pow(x2-x1,2) + pow(y2-y1,2); // Storing them
}
minimumDistance = distance[1];
//Finding smallest distance
for (int i = 2; i < 20; i++) {
if (distance[i] <= minimumDistance) {
closestPellet = i;
}
}
printf("Closest pellet %d \n", closestPellet);
return shm[closestPellet];
}
void moveLeft(int fish, int* shm) {
if (shm[0] <= 90) {
}
else{
fish--;
shm[0]--;
}
}
void moveRight(int fish, int* shm) {
if (shm[0] >= 99){
}
else{
fish++;
shm[0]++;
}
}
Pellets.c
// Multiple pellets
//Process ID, position, eaten/misse
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
void eatPellet();
void missPellet();
int main() {
key_t key = ftok("SwimMill.c", 'b');
int shmid = shmget(key, 1024, IPC_CREAT|0666);
int *shm = (int*) shmat(shmid, NULL, 0);
int i = 1; // 1 - 19 are pellets
for (; i < 20; i++) {
int pelletPosition = rand() % 9 + 0; // random number from 0 - 9
shm[i] = pelletPosition;
break;
}
while(1) {
if (shm[i] < 90) {
shm[i] += 10;
}
else if (shm[i] == shm[0]) {
eatPellet();
printf("Position: %d\n", shm[i] );
break;
// EATEN and KILL
}
else {
// KIll process, terminate
missPellet();
printf("Position: %d\n", shm[i] );
break;
}
// printf("%d\n",shm[i] );
i++;
sleep(1);
}
shmdt(shm);
return 0;
}
void eatPellet() {
printf("Pellet eaten!");
printf("PID: %d \n", getpid());
}
void missPellet() {
printf("Pellet missed");
printf("PID: %d \n", getpid());
}
For the makefile, I run "make". Then I run ./SwimMill
. However, it runs Fish
for some reason.
You're not using fork
/ exec
correctly:
while(timer <= 30){
sleep(1); // Slow process down
fish = fork();
execv("Fish", argv);
pellet[index] = fork();
execv("Pellets", argv);
printGrid(shm);
printf("\n");
timer++;
index++;
}
Recall that the fork
function returns twice: once to the parent process where it returns the child's pid, and once to the child process where it returns 0.
You're forking a new process, but not checking the return value. So both the child and the parent call execv
to start the "Fish" program, so you have two copies of "Fish" running and no copies of "SwimMill" running.
You need to check the return value of fork
to see if the process is the parent or the child and act accordingly.
while(timer <= 30){
sleep(1); // Slow process down
fish = fork();
if (fish == -1) {
perror("fork failed");
exit(1);
} else if (fish == 0) {
execv("Fish", argv);
perror("exec failed");
exit(1);
}
pellet[index] = fork();
if (pellet[index]== -1) {
perror("fork failed");
exit(1);
} else if (pellet[index] == 0) {
execv("Pellets", argv);
perror("exec failed");
exit(1);
}
printGrid(shm);
printf("\n");
timer++;
index++;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With