我有以下程序来练习使用分叉和共享内存。
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main() {
int bignum = 1000000;
key_t key = ftok(".", 'x');
int shmid = shmget(key, sizeof(int)*bignum, IPC_CREAT | 0666);
if (shmid < 0) {
perror("shmget\n");
return 1;
}
int *arr = shmat(shmid, NULL, 0);
pid_t c1 = fork();
if (c1==0) {
pid_t c2 = fork();
if (c2==0) {
pid_t c3 = fork();
if (c3==0) {
arr[0] = 10;
} else {
arr[1] = 11;
}
wait(NULL);
exit(0);
} else {
arr[2] = 12;
}
wait(NULL);
exit(0);
} else {
arr[3] = 13;
wait(NULL);
for (int i=0; i<4; i++) printf("%d ", arr[i]);
printf("\n");
}
shmdt(arr);
shmctl(shmid, IPC_RMID, NULL);
exit(0);
}
我之前使用较少的共享内存运行此程序,现在增加了共享内存,以查看这是否会对程序产生任何影响。当我运行此程序时,我得到:
shmget
: Invalid argument
我看过这个帖子:C linux shmget 参数无效
我尝试过遵循建议,但我不熟悉ipcs
和ipcrm
。我在终端中运行ipcs
,它给了我一些共享内存信息。但我无法分辨哪个是程序分配的,有很多,我无法分辨哪些可以安全删除,哪些不可以。
我觉得很奇怪,你不会在 C 程序内部这样做,所以这让我怀疑是否没有更好的方法来解决此问题。我特别不明白为什么调用shmdt
和shmctl
不会让这个问题不成问题。还有其他方法可以“撤消”内存共享吗?
编辑:该问题已被关闭,因为它与此类似:
但是,它使用了我的代码中已有的代码——因此它似乎无法回答这个问题。
编辑:这是我根据答案更新的代码。它确实解决了之前的问题,但现在经过一些错误检查后,引发了权限错误。
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main() {
size_t bignum = 1000000*sizeof(int);
key_t key = ftok(".", 'x');
int shmid = shmget(key, bignum, IPC_CREAT | 0666);
if (shmid == -1) {
shmctl(shmid, IPC_RMID, NULL);
shmid = shmget(key, bignum, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(1);
}
}
int *arr = shmat(shmid, NULL, 0);
if (arr == (int *)-1) {
perror("shmat");
exit(1);
}
shmdt(arr);
shmctl(shmid, IPC_RMID, NULL);
shmid = shmget(key, bignum, IPC_CREAT | 0666);
arr = shmat(shmid, NULL, 0);
pid_t c1 = fork();
if (c1==0) {
pid_t c2 = fork();
if (c2==0) {
pid_t c3 = fork();
if (c3==0) {
arr[0] = 10;
} else {
arr[1] = 11;
}
wait(NULL);
exit(0);
} else {
arr[2] = 12;
}
wait(NULL);
exit(0);
} else {
arr[3] = 13;
wait(NULL);
for (int i=0; i<4; i++) printf("%d ", arr[i]);
}
if (shmdt(arr) == -1) {
perror("shmdt");
exit(1);
}
if (shmctl(shmid, IPC_RMID, NULL) == -1) {
perror("shmctl");
exit(1);
}
exit(0);
}
具体来说,当我运行它时,结果是
shmget: Permission denied
旧程序在退出后留下了一个较小的共享内存段,因此附加到该段并请求更大的内存大小会失败。您可以通过删除它来启动新程序: