Компиляция неправильного файла? - PullRequest
0 голосов
/ 30 октября 2018

У меня есть 3 файла - SwimMill.c, Fish.c и Pellets.c - каждый из которых скомпилирован в исполняемый файл. Когда SwimMill запущен, он использует fork() и exec() для запуска Fish и Pellets. Однако по какой-то причине, когда я использую терминал, компилирую программы с make и запускаю SwimMill, файл Fish запускается первым. Кто-нибудь может мне помочь?

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());
}

Для make-файла я запускаю "make". Тогда я бегу ./SwimMill. Однако по какой-то причине он запускается Fish.

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Что заставляет вас думать, что Рыба бежит до SwimMill?

Если вы полагаетесь на порядок вывода в stdout, вы будете введены в заблуждение из-за буферизации "hello", которая не будет выводиться сразу, пока не будет записано либо '\n', либо fflush(stdout), либо процесс завершится ,

То есть SwimMill запускает в первую очередь, но Fish показывает вывод в первую очередь.

Изменение:

printf("Hello");

до

printf("Hello\n");

И аналогично:

printf("printing from fish");

до

printf("printing from fish\n");
0 голосов
/ 30 октября 2018

Вы неправильно используете fork / exec:

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++;
}

Напомним, что функция fork возвращает дважды: один раз в родительский процесс, где он возвращает pid дочернего процесса, и один раз в дочерний процесс, где он возвращает 0.

Вы запускаете новый процесс, но не проверяете возвращаемое значение. Поэтому дочерний элемент и родительский вызов execv вызывают программу «Рыба», поэтому у вас есть две запущенные копии «Рыба» и не запущенные копии «Плавь» ».

Вам необходимо проверить возвращаемое значение fork, чтобы увидеть, является ли процесс родительским или дочерним, и действовать соответственно.

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++;
}
...