我正在尝试在共享内存中共享一个链表,但是在使用fork()
时遇到了一些问题,没有fork()
它运行良好,但我必须至少有一个子进程。
如果没有子进程,它可以工作,但是当我创建一个子进程并使用addValue
函数时,结果是分段错误。
由于很多更改,代码不是很好。 我尝试使用malloc
但对于流程无法完成。
在一些论坛中搜索,对共享链表有不同的想法,但没有一个有效。
我的另一个疑问是关于shmget()
,我必须传递sizeof(struct Request)
但有时他们会传递sizeof(struct Request)*n
,如果链表可以处理的最大节点池,但有时他们会使用具有不同键的shmget
,就像我写的这段代码一样。所以另一个问题是:sizeof()*n
或size()
有多个shmget
键?
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <unistd.h>
#include <sys/ipc.h>
struct Request{
int value;
struct Request *next;
}Request;
void errorHandler(char *msg){
perror(msg);
exit(EXIT_FAILURE);
}
struct Request *getNode(key_t key){
int shmid = shmget(key, sizeof(struct Request), IPC_CREAT | 0660);
if(shmid==-1){
errorHandler("SHMGET7");
}
struct Request *req = shmat(shmid, NULL, 0);
if(req==(void *)-1){
errorHandler("SHMAT9");
}
return req;
}
void addValue(key_t headKey, key_t newKey, int value){
struct Request *head = getNode(headKey);
while(head->next!=NULL){
head = head->next;
}
struct Request *node = getNode(newKey);
node->value = value;
node->next = NULL;
head->next = node;
}
void printNodes(key_t key){
struct Request *head = getNode(key);
while(head!=NULL){
printf("%dn", head->value);
head = head->next;
}
}
int main(int argc, char *argv[]){
key_t key = 1234;
struct Request *req = getNode(key);
req->value = -1;
req->next = NULL;
key_t newKey = 250;
addValue(key, newKey, 100);
newKey = 251;
addValue(key, newKey, 101);
for(int i=0;i<2;i++){
pid_t pid = fork();
if(pid==-1){
errorHandler("FORK");
}else if(pid==0){
newKey = 252+i;
addValue(key, newKey, 101);
exit(0);
}
sleep(1);
}
for(int i=0;i<2;i++){
wait(NULL);
}
printNodes(key);
printf("endn");
return 0;
}
对于shmdt
我必须循环链接列表并shmdt
每个节点?
如果没有子进程,它可以工作,但是当我创建一个子进程并使用addValue函数时,结果是分段错误。
shmat(<id>, NULL, <flg>)
返回的地址仅对当前进程有效,在其他进程中使用它具有未定义的行为。
对于第一个分叉,列表包含来自父级的有效地址,因为子级继承了附加的共享内存段。但是在第二个回合(我重视 1(,第二个分叉尝试使用对它无效的地址,也不对printNodes
后面的主进程无效,因为来自第一个分叉并且只对它有效。出于同样的原因,假设主进程能够通过shmap
第二个分叉来获取地址返回,则该地址也不能被取消引用。
我必须传递大小(结构请求(,但有时...
这是正确的大小,因为您希望分配一个单元格,使用所需的大小相同malloc
。
解决问题的一种方法是使用密钥而不是当前进程及其子进程无效的地址来next
。
对代码进行最小的更改,使用 NULL 指针的键 0,修改后的定义是:
struct Request{
int value;
key_t next;
} Request;
和
void addValue(key_t headKey, key_t newKey, int value){
struct Request *head = getNode(headKey);
while(head->next!=0){
headKey = head->next;
head = getNode(headKey);
}
struct Request *node = getNode(newKey);
node->value = value;
node->next = 0;
head->next = newKey;
}
void printNodes(key_t key) {
while (key != 0) {
struct Request *head = getNode(key);
printf("%dn", head->value);
key = head->next;
}
}
在开头或主要:
req->next = 0;
之后,编译和执行(我添加了#include <sys/wait.h>
(:
pi@raspberrypi:/tmp $ gcc -g -Wall l.c
pi@raspberrypi:/tmp $ ./a.out
i=0
i=1
-1
100
101
101
101
end
pi@raspberrypi:/tmp $