c中的共享内存变量
Shared memory variable in c
我正在为 uni 分配作业,但在共享内存中定义全局变量 Bank 以便我的进程具有共享地址时遇到了问题。我们正在探索竞争条件,我应该让两个进程都调用 MakeTransactions() 然后使用信号量来消除竞争条件。目前,我将 运行 保留为关于共享内存的不同类型(int 与 struct)的错误。有人可以解释最好的方法是什么吗?任何的意见都将会有帮助。谢谢!
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
struct Bank {
int balance[2];
};
struct Bank = *bank;
// routine for thread execution
void* MakeTransactions() {
int i, j, tmp1, tmp2, rint;
double dummy;
for (i=0; i < 100; i++) {
rint = (rand()%30)-15;
if (((tmp1=bank->balance[0])+rint) >=0 &&
((tmp2=bank->balance[1])-rint)>=0) {
bank->balance[0] = tmp1 + rint;
for (j=0; j < rint*100; j++) {
dummy=2.345*8.765/1.234; // spend time on purpose
}
bank->balance[1] = tmp2 - rint;
}
}
return NULL;
}
int main(int argc, char **argv) {
int i;
void* voidptr = NULL;
bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
//check if bank is not NULL
bank->balance[0] = 100;
bank->balance[1] = 100;
pid_t pid;
srand(getpid());
printf("\nInit balances A:%d + B:%d ==> %d!",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
pid=fork();
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
if (pid == 0) {
printf("\nChild computing ...");
MakeTransactions();
printf("\nChild process complete");
printf("\nLet's check the balances A:%d + B:%d ==> %d ?= 200",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
return 0;
}
else {
printf("\nParent computing...\n");
MakeTransactions();
wait(NULL);
printf("\nParent process complete\n");
printf("Let's check the balances A:%d + B:%d ==> %d ?= 200\n\n",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
return 0;
}
return 0;
}
我将从对您的代码进行一些重构开始,这样您的评论中的 mmap 无法工作的原因就很清楚了。
使您的结构声明成为非匿名的:
struct Bank {
int balance[2];
};
还有你的全局:struct Bank bank = {{100,100}};
。现在,这个 bank
变量在堆栈上,这将使切换到 mmap 变得更加困难。引入间接:
struct Bank bankGlobal = {{100, 100}};
struct Bank *bank = &bankGlobal;
...
bank->balance[0] = tmp1 + rint;
现在,bank
是指向 struct Bank
的指针,目前指向 bankGlobal
。您需要将所有 bank.
更改为 bank->
。使用此代码,您可以切换到 mmap
解决方案。
首先,您不能在全局 space 中使用 mmap 初始化您的 bank 变量。它必须正常工作。其次,您试图获取指向 Bank (sizeof *Bank
) 的指针的大小,而您应该以整个结构大小为目标。
所以,改变这个:
-struct Bank bankGlobal = {{100, 100}};
-struct Bank *bank = &bankGlobal;
+struct Bank *bank;
在主函数中:
bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
//check if bank is not NULL
bank->balance[0] = 100;
bank->balance[1] = 100;
完成后不要忘记 munmap。
关于种族,可以放POSIX semaphore inside this Bank
struct, and protect this transaction, with sem_wait and sem_post.
我正在为 uni 分配作业,但在共享内存中定义全局变量 Bank 以便我的进程具有共享地址时遇到了问题。我们正在探索竞争条件,我应该让两个进程都调用 MakeTransactions() 然后使用信号量来消除竞争条件。目前,我将 运行 保留为关于共享内存的不同类型(int 与 struct)的错误。有人可以解释最好的方法是什么吗?任何的意见都将会有帮助。谢谢!
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
struct Bank {
int balance[2];
};
struct Bank = *bank;
// routine for thread execution
void* MakeTransactions() {
int i, j, tmp1, tmp2, rint;
double dummy;
for (i=0; i < 100; i++) {
rint = (rand()%30)-15;
if (((tmp1=bank->balance[0])+rint) >=0 &&
((tmp2=bank->balance[1])-rint)>=0) {
bank->balance[0] = tmp1 + rint;
for (j=0; j < rint*100; j++) {
dummy=2.345*8.765/1.234; // spend time on purpose
}
bank->balance[1] = tmp2 - rint;
}
}
return NULL;
}
int main(int argc, char **argv) {
int i;
void* voidptr = NULL;
bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
//check if bank is not NULL
bank->balance[0] = 100;
bank->balance[1] = 100;
pid_t pid;
srand(getpid());
printf("\nInit balances A:%d + B:%d ==> %d!",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
pid=fork();
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
if (pid == 0) {
printf("\nChild computing ...");
MakeTransactions();
printf("\nChild process complete");
printf("\nLet's check the balances A:%d + B:%d ==> %d ?= 200",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
return 0;
}
else {
printf("\nParent computing...\n");
MakeTransactions();
wait(NULL);
printf("\nParent process complete\n");
printf("Let's check the balances A:%d + B:%d ==> %d ?= 200\n\n",
bank->balance[0],bank->balance[1],bank->balance[0]+bank->balance[1]);
return 0;
}
return 0;
}
我将从对您的代码进行一些重构开始,这样您的评论中的 mmap 无法工作的原因就很清楚了。
使您的结构声明成为非匿名的:
struct Bank {
int balance[2];
};
还有你的全局:struct Bank bank = {{100,100}};
。现在,这个 bank
变量在堆栈上,这将使切换到 mmap 变得更加困难。引入间接:
struct Bank bankGlobal = {{100, 100}};
struct Bank *bank = &bankGlobal;
...
bank->balance[0] = tmp1 + rint;
现在,bank
是指向 struct Bank
的指针,目前指向 bankGlobal
。您需要将所有 bank.
更改为 bank->
。使用此代码,您可以切换到 mmap
解决方案。
首先,您不能在全局 space 中使用 mmap 初始化您的 bank 变量。它必须正常工作。其次,您试图获取指向 Bank (sizeof *Bank
) 的指针的大小,而您应该以整个结构大小为目标。
所以,改变这个:
-struct Bank bankGlobal = {{100, 100}};
-struct Bank *bank = &bankGlobal;
+struct Bank *bank;
在主函数中:
bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
//check if bank is not NULL
bank->balance[0] = 100;
bank->balance[1] = 100;
完成后不要忘记 munmap。
关于种族,可以放POSIX semaphore inside this Bank
struct, and protect this transaction, with sem_wait and sem_post.