共享内存中的LinkedList

问题描述 投票:0回答:1

我正在尝试在共享内存中共享一个链表,但是在使用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("%d\n", 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("end\n");

  return 0;
}

对于shmdt,我必须循环链接列表,并shmdt每个节点?

c linked-list shared-memory
1个回答
0
投票

如果没有子代,它将起作用,但是当我创建一个子代进程并使用addValue函数时,结果是分段错误。

shmat(<id>, NULL, <flg>)返回的地址仅对当前进程有效,要在其他进程中使用它具有未定义的行为。

对于第一个fork,该列表包含来自父级的有效地址,因为子级继承了附加的共享内存段。但是在第二个回合(i值为1),第二个fork尝试使用一个无效的地址,也不使用printNodes中稍后的主进程,因为它来自第一个fork] >并且仅对此有效。出于相同的原因,假设主进程能够通过shmap获得第二个fork的地址返回,该地址也不能被取消引用。


我必须传递sizeof(struct Request),但有时...

这是正确的大小,因为您要分配一个单元格,使用malloc所需的大小是相同的。


解决问题的一种方法是将密钥用于next,而不是在当前进程及其子进程中无效的地址。

对代码进行最小的更改,使用键0作为NULL指针,修改后的定义是:

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("%d\n", head->value);
    key = head->next;
  }
}

以及开头或main

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 $ 
© www.soinside.com 2019 - 2024. All rights reserved.