在具有活动等待的 child 进程之间共享内存时出现 C 错误
C Error when sharing memory between child process with active wait
我正在尝试编写一个在 child 进程和父进程之间共享内存的程序。该程序还使用叉子。
练习的目的是:
-Father 发送到child(带共享内存)3次一个vector with active wait
-Child 接收 vec,打印它并更改同步变量
Struct:
typedef struct{
int change[NUM_TOTAL];
int synchronize;
}Exchange;
Exchange *vec;
int fd = shm_open("/shmtest8",O_CREAT| O_RDWR,S_IRUSR|S_IWUSR);
//Check shm_open error
ftruncate(fd, 100);
vec = (Exchange*) mmap(NULL,100,PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
x = forkFunc() //Creates a fork, and return 0 to parente and > 0 to child process
if(x == 0){ //Parent
int cont = 0;
while(cont != 3){
printf("Father\n");
vec->synchronize = 1; //Now go to to the child
while(vec->synchronize!=0); //the child change the variable to 0
cont++;
printf("cont %d",cont);
}
wait(NULL);
munmap(vec,sizeof(vec));
close(fd);
shm_unlink("/shmtest8");
}else if(x > 0){ //Child
int cont = 0;
while(vec->synchronize!=1); //Exit while when father change the variable to 1
int i;
for(i = 0; i < 10; i++){
printf("%d\t",i);
}
vec->synchronize =0; //Return to the father
}
这是一个输出示例:
Father
Child
0 1 2 3 4 5 6 7 8 9
cont 1
Father
第一次迭代后程序在 "while(vec->synchronize!=0);" 后冻结...我想问题存在于 child 过程中,但我不知道为什么...有什么想法吗?
谢谢
不知道,但我可以告诉你,只要两个线程写入同一个变量 (vec->synchronize
),你就有麻烦了。对于这样的同步,请允许我推荐管道或semaphores。仅当只有一个线程写入时或使用其他机制(如信号量或互斥量)来控制对共享内存的访问时才使用共享内存。
如果您不能使用信号量,请改用信号和信号处理程序。如果你不能使用信号,我可以看到另外两个解决方案:
当您的代码处于临界区(修改共享内存)时,使用掩码来阻止所有信号。这样可以确保数据共享内存没有损坏。
您应该使用原子函数,例如 Test&Set,而不是 while(vec->synchronize!=1)
。问题在于它很难在软件中实现。
现在,这些已经不是很好的解决方案的最大缺点是它们不能在多处理器系统中工作。
我认为你的子进程部分应该有 1 个 while 循环
while(cont != 3){
while(vec->synchronize!=1); //Exit while when father change the variable to 1
int i;
for(i = 0; i < 10; i++){
printf("%d\t",i);
}
ec->synchronize =0; //Return to the father
cont++
}
我正在尝试编写一个在 child 进程和父进程之间共享内存的程序。该程序还使用叉子。
练习的目的是: -Father 发送到child(带共享内存)3次一个vector with active wait
-Child 接收 vec,打印它并更改同步变量
Struct:
typedef struct{
int change[NUM_TOTAL];
int synchronize;
}Exchange;
Exchange *vec;
int fd = shm_open("/shmtest8",O_CREAT| O_RDWR,S_IRUSR|S_IWUSR);
//Check shm_open error
ftruncate(fd, 100);
vec = (Exchange*) mmap(NULL,100,PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
x = forkFunc() //Creates a fork, and return 0 to parente and > 0 to child process
if(x == 0){ //Parent
int cont = 0;
while(cont != 3){
printf("Father\n");
vec->synchronize = 1; //Now go to to the child
while(vec->synchronize!=0); //the child change the variable to 0
cont++;
printf("cont %d",cont);
}
wait(NULL);
munmap(vec,sizeof(vec));
close(fd);
shm_unlink("/shmtest8");
}else if(x > 0){ //Child
int cont = 0;
while(vec->synchronize!=1); //Exit while when father change the variable to 1
int i;
for(i = 0; i < 10; i++){
printf("%d\t",i);
}
vec->synchronize =0; //Return to the father
}
这是一个输出示例:
Father
Child
0 1 2 3 4 5 6 7 8 9
cont 1
Father
第一次迭代后程序在 "while(vec->synchronize!=0);" 后冻结...我想问题存在于 child 过程中,但我不知道为什么...有什么想法吗?
谢谢
不知道,但我可以告诉你,只要两个线程写入同一个变量 (vec->synchronize
),你就有麻烦了。对于这样的同步,请允许我推荐管道或semaphores。仅当只有一个线程写入时或使用其他机制(如信号量或互斥量)来控制对共享内存的访问时才使用共享内存。
如果您不能使用信号量,请改用信号和信号处理程序。如果你不能使用信号,我可以看到另外两个解决方案:
当您的代码处于临界区(修改共享内存)时,使用掩码来阻止所有信号。这样可以确保数据共享内存没有损坏。
您应该使用原子函数,例如 Test&Set,而不是
while(vec->synchronize!=1)
。问题在于它很难在软件中实现。
现在,这些已经不是很好的解决方案的最大缺点是它们不能在多处理器系统中工作。
我认为你的子进程部分应该有 1 个 while 循环
while(cont != 3){
while(vec->synchronize!=1); //Exit while when father change the variable to 1
int i;
for(i = 0; i < 10; i++){
printf("%d\t",i);
}
ec->synchronize =0; //Return to the father
cont++
}