Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiling the wrong file?

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.

like image 316
Slay Avatar asked Oct 30 '18 20:10

Slay


Video Answer


1 Answers

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++;
}
like image 121
dbush Avatar answered Sep 30 '22 03:09

dbush