首页 > 解决方案 > C中结构的副本

问题描述

在 c 的项目中,我必须从 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-scheduler 不是最好的主意,但这是我们在讲座中必须做的,所以我们别无选择。

完整的代码,但有点长(我是法国人,所以注释是法语的)

#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
}

标签: cstructshared-memorymemcpy

解决方案


memcpy您显示的通话有两个主要问题,还有一个小问题:

  1. &input您作为源指针传递。这里的问题是这&input是一个指向变量的指针input,而不是指向共享内存input的指针。这意味着您复制指针而不是指向的数据。要解决此问题,请使用 plain input

  2. 作为您使用的大小sizeof(input),它是指针本身的大小,而不是它指向的大小。您可能要复制sizeof carList的大小是 ,它是目标数组的大小(以字节为单位)。

  3. 小问题是你使用的目的地&carList。这是一个指向数组的指针,类型为f1 (*)[20]. 您需要的是指向数组第一个元素的指针,即&carList[0], 或 plain carList(相同)。

所以电话应该看起来像

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

推荐阅读