C中结构的副本
copy of a struct in 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 的数组,使table 的所有时间都来自汽车。我知道使用 cpu-scheduler 不是最好的主意,但这是我们在讲座中必须做的,所以我们别无选择。
full code but it's a bit long (and i'm french so the notes are in french)
#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
}
memcpy
call you show 有两个主要问题,还有一个小问题:
您将 &input
作为源指针传递。这里的问题是 &input
是指向变量 input
的指针,而不是指向 input
指向的共享内存的指针。这意味着您复制 pointer 而不是指向的数据。要解决此问题,请使用普通 input
.
作为您使用的大小 sizeof(input)
,这是 指针本身的大小 ,而不是它所指向的大小。您可能要复制的大小是 sizeof carList
,这是目标数组的大小(以字节为单位)。
小问题是目的地,你用的地方&carList
。这是一个指向数组的指针,类型为 f1 (*)[20]
。您需要的是指向数组第一个元素的指针,即 &carList[0]
,或普通的 carList
(相同)。
所以调用应该看起来像
memcpy(carList, input, sizeof carList); // Copy from the shared memory into our local array
在 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 的数组,使table 的所有时间都来自汽车。我知道使用 cpu-scheduler 不是最好的主意,但这是我们在讲座中必须做的,所以我们别无选择。
full code but it's a bit long (and i'm french so the notes are in french)
#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
}
memcpy
call you show 有两个主要问题,还有一个小问题:
您将
&input
作为源指针传递。这里的问题是&input
是指向变量input
的指针,而不是指向input
指向的共享内存的指针。这意味着您复制 pointer 而不是指向的数据。要解决此问题,请使用普通input
.作为您使用的大小
sizeof(input)
,这是 指针本身的大小 ,而不是它所指向的大小。您可能要复制的大小是sizeof carList
,这是目标数组的大小(以字节为单位)。小问题是目的地,你用的地方
&carList
。这是一个指向数组的指针,类型为f1 (*)[20]
。您需要的是指向数组第一个元素的指针,即&carList[0]
,或普通的carList
(相同)。
所以调用应该看起来像
memcpy(carList, input, sizeof carList); // Copy from the shared memory into our local array