shmget shmat 无法正常工作 [关闭]

Posted

技术标签:

【中文标题】shmget shmat 无法正常工作 [关闭]【英文标题】:shmget shmat is not working properly [closed] 【发布时间】:2013-06-10 20:47:48 【问题描述】:
    class test_class
    
       public:
       std::string str;
       int ival;
    ;

    int main()
    
        int shmkey = 3450;
        int shmid;

        if((shmid = shmget(shmkey, sizeof(test_class*), IPC_CREAT | 0666)) < 0)
        
            perror("shmget");
            exit(1);
        

        test_class **test_obj;
        if((test_obj = (test_class**) shmat(shmid, NULL, 0)) == (test_class**) -1)
        
            perror("shmat");
            exit(1);
        

        test_class* new_obj = new test_class();
        *test_obj = new_obj;

        (*test_obj)->str = "parent process string";
        (*test_obj)->ival = 9;

        pid_t pid = fork();

        if(pid == 0)
        
            int shmkey = 3450;
            int shmid;

            if((shmid = shmget(shmkey, sizeof(test_class*), 0666)) < 0)
            
                perror("shmget");
               exit(1);
            

            test_class **test_obj;
            if((test_obj = (test_class**) shmat(shmid, NULL, 0)) == (test_class**) -1)
            
                perror("shmat");
                exit(1);
            

            (*test_obj)->str = "child process string";
            (*test_obj)->ival = 10;

            exit(EXIT_SUCCESS);
        

        sleep(3);
        std::cout << (*test_obj)->str << std::endl;
        std::cout << (*test_obj)->ival << std::endl;

        shmctl(shmid, IPC_RMID, 0);

        return 0;
    


This code output is :-
child process string
9

在这个程序中,我正在更新子进程中的共享内存对象(在堆内存中)并在父进程中打印更新的值。正如我们从输出中看到的,它正确地更新了字符串而不是 int。因为它在堆内存中,所以它不应该更新。这里的字符串是如何更新的?

这方面有什么帮助吗?

谢谢, 高拉夫

【问题讨论】:

【参考方案1】:

您的代码有几个问题:

1) 父进程不会等待子进程完成对对象的修改,因此无法预测它会输出什么。在输出值之前将wait(NULL)放入父进程;

2) 子进程改变了一个std::string,实际上它改变了string对象内部的一些指针,但是子进程和父进程的堆不同,地址空间不同,所以这是非常危险的。您应该将 char 数组存储在共享内存中;

3) 在子进程中不需要执行shmget&shmat,因为共享内存已经在父进程中获得并在fork中复制;

4) 您应该将test_class 的字段指定为volatile,这样编译器就不会优化读取它们的值。

【讨论】:

5) 您正在使用*test_obj = new test_class(); 在共享内存块中存储指向非共享内存的指针。这将在您的示例程序中起作用,但这只是因为整个地址空间被有效地复制到fork() 的子进程中。 是的,谢谢,我忽略了这一点——我以为他在那里存储了一个对象而不是一个指针。 如果我存储对象,我认为不会出现这个问题。无论如何,我的观点在这里,字符串如何在子进程中更新,因为它也在堆内存中? 字符串在父进程中没有更新。我刚刚编译了您的代码,并按原样打印了“父字符串”。也许你没有向我们展示真正的代码? 感谢启发!你是对的,它不是真正的代码。我明白了,这是因为我在真实代码中的一个错误。字符串也没有更新。

以上是关于shmget shmat 无法正常工作 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

linux 共享内存 shmat,shmget,shmdt,shmctl

Linux进程间通信 -- 共享内存 shmget()shmat()shmdt()shmctl()

Linux C语言进程间通信 共享内存(Shared Memory)shmget()shmat()shmdt()shmctl() ipcs -mipcrm -m

Linux C语言进程间通信 共享内存(Shared Memory)shmget()shmat()shmdt()shmctl() ipcs -mipcrm -m

c 共享内存demo

共享内存在 Linux 中是如何在幕后工作的?