копия структуры в C - PullRequest
       32

копия структуры в C

0 голосов
/ 06 ноября 2019

в проекте в c Я должен скопировать массив struct из sharedMemory

я делаю:

int status = 0;
pid_t wpid;
f1 *input = (f1*) shmat(shmid,0,0);
while ((wpid = wait(&status)) > 0){
    memcpy(&carList, &input, sizeof(input));
}

f1 - это моя структура автомобиля.

но в carList ничего не копируется, но значения вводятся сыном. Процесс Я думаю, что проблема в этой части кода, я пробовал использовать множество других возможностей, но я не нашел нигде.

Мне нужно использовать разделяемую память, чтобы создать 20 сыновей и заставить их генерировать случайные моменты времени для гонок, подобных машине.

Итак, я создал 20 сыновей, которые я связал с записью массива их структури заставьте их написать в нем время, которое они сгенерируют.

Затем, время от времени, отец копирует массив struct для создания динамической таблицы всего времени из автомобилей. Я знаю, что использование CPU-планировщика не лучшая идея, но это то, что мы должны сделать в лекции, поэтому у нас нет выбора.

полный код, но он немного длинный (и яФранцузский, так что записи на французском)

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> // bool
#include <unistd.h> //fork
#include <string.h> //strcat
#include <sys/wait.h> //wait
#include <sys/types.h>
#include <sys/shm.h>

#define TURN 3
#define SECTION 3
#define CAR 20
#define KEY 666
#define STANDPOURCENT 10

typedef struct {
    int number;
    int stands;
    bool out;
    int totalTime;

    int circuit[TURN][SECTION];
} f1;

int carListNumber[CAR] = {7, 99, 5, 16, 8, 20, 4, 55, 10, 26, 44, 77, 11, 18, 23, 33, 3, 27, 63, 88};
f1 carList[CAR];
/***********************************************************************************************************************
 *                               fonctions
 **********************************************************************************************************************/

/**
 * renvois un nombre compris entre 40 et 45 secondes pour le
 * clacul du temps des tours de circuits
 * @return integer between 40 and 45
 */
int genSection(){
    int time = 45 - (rand() % 9);
    sleep(time/20);
    return time; // gestion du random et du temps perdu
}

/**
 * génération du temps d'arret au stand
 * @return integer between 2 and 5
 */
int genRandomStand(){
    return  5 - (rand() % 3);
}

/**
 * génération nombre entre 1 et 100
 * @return int between 1 and 100
 */
int genRandom(){
    return 100 - (rand() % 100);
}

/**
 * clear de la console
 */
void clrscr(){
    system("clear");
}

/**
 * affichage du tableau de résultat de tout les tours pour toutes les voitures et sections
 */
void showRun(){
    clrscr();
    for (int turn = 0; turn < TURN; turn++){
        for(int car = 0; car < CAR; car++){
            printf("Voiture %3d || turn : %3d ||S1 : %1d | S2 : %2d | S3 : %2d  || Total Turn : %3d \n",carList[car].number,
                   turn+1,
                   carList[car].circuit[turn][0],
                   carList[car].circuit[turn][1],
                   carList[car].circuit[turn][2],
                   carList[car].circuit[turn][0]+carList[car].circuit[turn][1]+carList[car].circuit[turn][2]);
        }
        printf("---------------------------------------------------------------------------------------------------------------\n");
    }
}

/**
* generation de la liste des structur voitrure sur base de la liste des numero de voitures
* @return void
*/
void init_car_list(int *carListNumber){
    for(int i = 0; i < CAR; i++){
        carList[i].number = carListNumber[i];
        carList[i].stands = 0;
        carList[i].out = false;
        carList[i].totalTime = 0;
        memset(carList[i].circuit, 0, sizeof(carList[i].circuit));
    }
}

/**
 * initalistation de la voiture passé en param
 * @param carNumber
 */
f1 init_car(int carNumber){
    f1 tmp;
    tmp.number = carNumber;
    tmp.stands = 0;
    tmp.out = false;
    tmp.totalTime = 0;
    memset(tmp.circuit, 0, sizeof(tmp.circuit));
    return tmp;
}

/**
 * fonction du code du fils (voiture)
 */
void circuit_son(int shmid,int carPosition){
    int carNumber = carListNumber[carPosition];
    //printf("in son %d : car number %d\n",carPosition,carNumber);
    f1 *output = (f1 *) shmat(shmid, 0, 0);
    printf("Départ de la voiture %d\n",carNumber);
    f1 *currentCar;
    srand(time()+getpid()); // génération du nouveau random pour chaque fils
    //printf("récupération de la strcuct voiture %d \n",carNumber);
    for(int i = 0; i < CAR; i++){
        if(output[i].number == carNumber){
            currentCar = &output[i];
            //printf("Récupération de :: output %d || carNumber %d || current car %d \n",output[i].number,carNumber,currentCar->number);
            break;
        }
    }
    for(int i = 0; i < TURN; i++){ // pour chaque tour
        for(int j = 0; j < SECTION; j++){ // pour chaque section du tour
            currentCar->circuit[i][j] = genSection();
            printf("car %d , %d \n",currentCar->number,currentCar->circuit[i][j]);
        }
        if (genRandom() > STANDPOURCENT || (i == (TURN-1) && currentCar->stands == 0)){ // 50% de s'arreter ou si jamais arrêter pendant la course
            currentCar->circuit[i][SECTION-1] += genRandomStand();
            printf("arret de la voiture %d au stand , temps total de la section 3 : %d \n",currentCar->number,currentCar->circuit[i][SECTION-1]);
            currentCar->stands++;
        }
    }
    exit(EXIT_SUCCESS);
}

/**
 * fonction du père
 * @return
 */
void circuit_father(int shmid){
    int status = 0;
    pid_t wpid;
    // récupération des données de la SM
    f1 *input = (f1*) shmat(shmid,0,0);
    while ((wpid = wait(&status)) > 0){ // temps que un processus est en cours
        memcpy(&carList, &input, sizeof(input));
        printf("input %d %d %d \n",input[4].circuit[1][0],input[4].circuit[1][1],input[4].circuit[1][2]);
        //showRun();
        printf("show run here in father || %d %d %d\n",carList[4].circuit[1][0],carList[4].circuit[1][1],carList[4].circuit[1][2]);
    }
}

/**
 * gestion des tours d essais des voitures
 * @param shmid id de la memoire partagée
 * @return -1 if error else 0
 */
int gen_circuit(int shmid) {
    for (int car = 0; car < CAR; car++) {
        int pid = fork();
        if (pid < 0) {
            perror("error on creation of car");
            printf("\n");
            return -1;
        }
            /* Son */
        else if (pid == 0) {
            circuit_son(shmid,car);
        }
    }
    /* Parent */
    circuit_father(shmid);
    return 0;
}

/**
 * initalisation de la shared memory
 */
void init_mem(shmid){
    f1 *mem = (f1 *) shmat(shmid, 0, 0);
    for(int i = 0; i < CAR; i++){
        mem[i] = init_car(carListNumber[i]);
    }
}

/**
 *
 * @return
 */
int main(){
    // initalisation des voitures
    init_car_list(carListNumber);
    // allocation de la mem partagée
    int shmid = shmget(KEY, (20 * sizeof(f1)),0666 | IPC_CREAT); // 0775 || user = 7 | groupe = 7 | other = 5
    if (shmid == -1){
        perror("ERROR in creation of the Shared Memory");
        printf("\n");
        shmctl(shmid,IPC_RMID,NULL); // suppression de la memoire partagée
        return 1;
    }
    init_mem(shmid);
    // gestion du circuit

    gen_circuit(shmid);
    printf("tout les tours sont terminé \n");
    printf("affichage des Résultats : \n");
    //showRun();

    // fin de la course
    printf("fin des tours \n");
    shmctl(shmid,IPC_RMID,NULL); // suppression de la memoire partagée
    return 0; // fin du programme
}

1 Ответ

0 голосов
/ 06 ноября 2019

Существует две основные проблемы с отображаемым вызовом memcpy и одна незначительная проблема:

  1. Вы передаете &input в качестве указателя источника. Проблема в том, что &input - это указатель на переменную input, а не указатель на разделяемую память, на которую указывает input. Это означает, что вы копируете указатель , а не данные, на которые указывают. Для решения этой проблемы используйте обычный input.

  2. . В качестве размера вы используете sizeof(input), который является размером самого указателя , а не размеромна что это указывает. Размер, который вы, вероятно, хотите скопировать, равен sizeof carList, который является размером целевого массива (в байтах).

  3. Незначительная проблема - это место назначения, где вы используете &carList,Это указатель на массив, имеющий тип f1 (*)[20]. Вам нужен указатель на первый элемент массива, который является &carList[0] или обычным carList (то же самое).

Так что вызов, вероятно, должен выглядетькак

memcpy(carList, input, sizeof carList);  // Copy from the shared memory into our local array
...