我想同步三种不同的过程,所以我想使用在进程之间共享内存。所以我从一个进程中分出了两个孩子,并在创建孩子之前创建了共享内存段。 我的意图是在不同的内核中运行子进程和父进程以使其并行执行。所以我使用亲和力控制来分配相应的CPU。这两个孩子都将在无限期等待while循环(在分配的同一个CPU上使用),直到它通过共享内存从父级获取触发器。所以当父母写入一些特定的字符/字符串时,孩子应该出来循环并开始执行其余的代码。
问题:
的变量“SHM”即共享内存的变化是不是子进程可见,从不出来while循环。
一些判断:
我觉得这个问题是因为它不被无效并提出了处理移动到特定内核后脏的L2缓存。所以核心仍然指向共享内存的旧值。只有当优化级别超过“0”时才会发生这种情况,即O2。当我强迫它到O0时,那么问题就看不到了。我对Linux内核和处理器本身的缓存背景不太了解。所以我暂时修改了代码,以便使用“volatile”从RAM中引用变量来摆脱这个问题。
实施例:
要查看真实这个问题,我已附加示例代码,其不与在“目的”说明。
我的问题:
这是预期的结果?
因此Linux不会在不同的CPU内核之间共享运行 的进程之间的内存吗?
至少AFAIK,内核总是会在相同内核中调度相同类型的进程,所以很难在不强制进程转移到其他内核的情况下实现这种情况。
/*
* Compilation commands:
* gcc -Wall -Wextra -O2 -o ./bin/share ./share.c
* - Optimization enabled, "volatile" is mandatory
* - Without "volatile" child1 and child2 indefinite loop
*
* gcc -Wall -Wextra -O0 -o ./bin/share ./share.c
* - Problem not seen
*
* Root cause of the problem is L2 cache, as it is private to core
*/
/* Linux includes */
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
/* Library includes */
#include
#include
int main(void) {
int rc;
int shmid;
int no_cpu;
/* volatile char *shm = NULL; <== uncomment to get rid of the problem */
char *shm = NULL;
cpu_set_t cpu;
size_t size = 10;
pid_t child1, child2;
no_cpu = sysconf(_SC_NPROCESSORS_ONLN);
if(no_cpu < 3) {
printf("ERROR: Minimum 3 CPU cores required\n");
printf("If you have only two CPU's, adjust the CPU_SET accordingly\n");
return -1;
}
CPU_ZERO(&cpu);
shmid = shmget(getpid(), size, IPC_CREAT);
if(shmid < 0) {
perror("Fail to get shared memory");
return -1;
}
if((shm = shmat(shmid, NULL, 0)) == (char *)-1) {
perror("Fail to attach to shared memory");
return -1;
}
child1 = fork();
if(child1 == 0) {
child2 = fork();
if(child2 == 0) { /* Parent */
CPU_SET(0, &cpu); /* Run on CPU 0 */
rc = sched_setaffinity(getpid(), sizeof(cpu), &cpu);
if(rc != 0) {
printf("Unable to set affinity to [%d] parent\n", getpid());
kill(child1, SIGTERM);
kill(child2, SIGTERM);
waitpid(child1, NULL, 0);
waitpid(child2, NULL, 0);
return -1;
}
printf("[%d] parent running in [%d]\n", getpid(), sched_getcpu());
*shm = 'a';
waitpid(child1, NULL, 0);
waitpid(child2, NULL, 0);
shmdt((void *)shm);
}
else if(child2 > 0) { /* Kid 2 */
CPU_SET(1, &cpu); /* Run on CPU 1 */
rc = sched_setaffinity(getpid(), sizeof(cpu), &cpu);
if(rc != 0) {
printf("Unable to set affinity to [%d] child2\n", getpid());
return -1;
}
printf("[%d] child2 running in [%d]\n", getpid(), sched_getcpu());
while(*shm != 'a');
shmdt((void *)shm);
exit(0);
}
else {
printf("Fork failed\n");
kill(child1, SIGTERM);
waitpid(child1, NULL, 0);
return -1;
}
}
else if(child1 > 0) { /* Kid 1*/
CPU_SET(2, &cpu); /* Run on CPU 2 */
rc = sched_setaffinity(getpid(), sizeof(cpu), &cpu);
if(rc != 0) {
printf("Unable to set affinity to [%d] child1\n", getpid());
return -1;
}
printf("[%d] child1 running in [%d]\n", getpid(), sched_getcpu());
while(*shm != 'a');
shmdt((void *)shm);
exit(0);
}
else {
printf("Fork failed\n");
return -1;
}
return 0;
}
+2
为什么使用'mmap(...,MAP_SHARED,...)'会执行sysV共享内存?你为什么期望'getpid()'返回一个有效的sysV'key_t'?你甚至可以阅读任何你正在尝试使用的函数的单页手册页吗? –
+2
缓存管理是操作系统的问题。您可以确定L2(或任何其他级别)缓存没有问题。总是先找到你身边的错,而不是别人的错! –
+0
你真的不应该像这样使用共享内存进行同步。这是一个信号量或两个信号的理想场所。 –