如何在两个进程之间共享链表?

3
我有两个进程,想在它们之间共享一个链表。其中一个进程只会读取列表,而另一个进程将修改列表(添加/删除条目)。你能告诉我如何实现吗?
更多细节:该语言为C,平台为Linux。共享内存似乎是一种方法,但我不知道如何实现。
如果有人能告诉我实现的方法,那将对我大有帮助。
我的一个想法是:我是否可以创建一个大小为节点的共享内存段?然后像使用malloc那样简单处理就行了。我的意思是,我将使用shmget(key, SHMSZ, IPC_CREAT | 0666)创建共享内存,其中SHMSZ将是结构体节点的大小。因此,我只在两个进程之间共享列表头。列表中的第一个条目除了链接条目指向列表中的下一个条目之外,所有值都为0,并且该条目是使用malloc创建的,因为在我的应用程序中,一个进程只会读取,而另一个进程会添加/删除列表中的条目。
我收到了一条回复,告诉我我不能使用malloc。我不知道为什么会这样。你能告诉我为什么我不能使用malloc吗?
以下是我尝试过的上述目的的代码,但出现了分段错误。
struct node
{
    int val;
    struct node* next;
};

void append(struct node *q,int val);
main()
{

    key_t key = 5678;

    int shmid;

    struct node *head;

    if ((shmid = shmget(key, sizeof(struct node), IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    };

    head = struct node*(shmat(shmid, (void *) 0, 0));

    head->val = 0;
    head->next= 0;

    append(head,2);
    append(head,5);
    append(head,6);

    exit(0);
}

void append(struct node *q,int val)

{
    struct node *temp1,*temp2;

    if (q->next == 0)

    {
        temp1=malloc(sizeof(struct node));
        temp1->val = val;
        temp1->next = 0;
        q->next = temp1;
    }

    else

    {
        temp2=malloc(sizeof(struct node));
        temp2->val = val;

        temp1 = q->next;
        while(1)
        {
            if (temp1 == 0)
            {
                temp1=temp2;
                break;
            }
            else
                temp1=temp1->next;
        }
    }

    return;

}

2
平台?编程语言? - anon
它们是同时运行的,我假设?您需要某种锁或互斥量来确保读取过程不会读取正在添加一半的条目。修改进程锁定列表,添加或删除条目,然后解锁它。 - Vanessa MacDougal
4个回答

2

我不知道Beej是谁,但他写的指南非常出色,而且他还为共享内存段编写了一篇指南。


1

你有几个选项:

  • 使用进程间通信(套接字,命名管道等)将重复的列表发送到每个需要副本的进程。你将有重复的列表,这可能意味着你会承担重复工作,并且你将面临同步列表的问题 - 这可能与你的问题相关或不相关。
  • 使用列表服务器和进程间通信来请求或设置列表元素。你需要优雅地处理客户端没有返回列表项的情况(可能是通过心跳和/或保留时间实现)
  • 使用共享内存直接在进程之间共享列表。你需要非常小心地锁定,并且它不能跨越不同的系统。
  • 使用fork(),并让子进程继承列表。像第一种解决方案一样,你最终将得到具有重复工作或重复元素的重复列表。(潜在地)。像第三个解决方案一样,这无法跨系统工作。
  • 使用上述方法的某种组合。

0

简单的回答:不要这样做。

多进程的好处在于你没有共享内存。这使你与其他进程隔离开来。设置一个“仅数据”的屏障可以为你的设计和鲁棒性带来巨大的好处。

相反,让生产进程将新数据(作为数据)发送到消费进程。这可以通过 STDIN/STDOUT、套接字甚至是低技术的文件来完成。


0
你不能使用malloc为每个节点分配内存的原因是,malloc返回一个指向给定进程堆中的指针。该指针对于另一个进程来说毫无意义,因为它有自己的堆。该地址在两个进程中可能是有效的,但它所引用的“物理”内存将是不同的。
如果你正在使用shmget,则需要为每个节点使用它(或创建一个更大的块,然后像已经建议的那样使用偏移量)。如果为每个节点使用单独的shmget调用,则键可以是列表中的next指针。这将是一种“简单”的实现方式,但可能不是一个好主意。我相信共享内存对象有系统范围的限制。我认为它由SHMMNI定义,在我刚检查过的系统上为4096。
另一种实现方式是,只需使一个进程成为列表的所有者(创建和删除节点的进程)。然后使用单个共享内存对象在两个进程之间通信以分发单个节点。然后使用共享信号量(semget、semop等)进行同步。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接