共享内存可以用指针操作吗?

bandaoyu 2018-03-17 02:14:35
现在有这样一个情况,就是进程A开辟了一个共享内存 shareM ,存放MAX_NUM个student的数据,进程B从共享内存中读取student数据。


type def tgSTUDENT

{

int32 type;

int32 age;

int8 name[128];


……


}STUDENT;



struct tgCLASS{

int32 studentNum;


STUDENT student[0];


}MYCLASS;


MYCLASS pmyClass = NULL;


pmyClass = (MYCLASS*)malloc(sizeof((MYCLASS) + N*sizeof(STUDENT));


因为获取的时候不是每个学生都获取,而是获取里面type等于某个数值的student。


现在同事给写的读取共享内存的代码是GetStudent(),直接将myClass 从共享内存中读出来,我读出来后还得

从myClass中逐一的判断student.type是否满足,然后放到申请的内存当中。


因而每次都要申请MAX_NUM个学生的空间sizeof((MYCLASS) + MAX_NUM*sizeof(STUDENT),很是浪费空间,拷贝无用的数据也消耗资源。


因此我就想,共享内存能不能返回一个指针,指针指向共享内存中MYCLASS的首地址,比如返回一个pshMyClass,这样我就不用申请buff然后将共享内存的数据拷贝到buff才能用,


而是直接操作指针pshMyClass,读取student的数据了。比如pshMyClass->studentNum,pshMyClass->student[i].type 等。



共享内存返回的地址是进程的逻辑地址,因而不能? ----共享内存是在同一台机器上的,因而每一个进程的逻辑地址都会对应一个物理地址,那么用没有可能返回这个物理地址,这样其他进程获取后不就可以使用了吗?


进程重启后,物理地址改变,所以不能?----我想这个可能是原因吧




如果不可以,想尽可能少的申请空间拷贝共享内存数据到当前进程做判断,有什么好的方案吗?
...全文
701 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2018-03-19
  • 打赏
  • 举报
回复
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
bandaoyu 2018-03-19
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
赵老师,你对paschen回答中提到的 ReadProcessMemory/WriteProcessMemory 方法怎么看?
bandaoyu 2018-03-19
  • 打赏
  • 举报
回复
引用 4 楼 paschen 的回复:
你可以读到指针的值,但不同程序中这个值是指向各自程序自身的虚拟内存中,当然后你可以用ReadProcessMemory/WriteProcessMemory读写其他进程的内存
厉害,还有这种操作。ReadProcessMemory/WriteProcessMemory是C、C++都有吗? 还是只是C++
bandaoyu 2018-03-19
  • 打赏
  • 举报
回复
引用 8 楼 paschen 的回复:
引用 5 楼 bandaoyu的回复:
[quote=引用 4 楼 paschen 的回复:] 你可以读到指针的值,但不同程序中这个值是指向各自程序自身的虚拟内存中,当然后你可以用ReadProcessMemory/WriteProcessMemory读写其他进程的内存
厉害,还有这种操作。ReadProcessMemory/WriteProcessMemory是C、C++都有吗? 还是只是C++
这是WINDOWS SDK,只要WINDOWS上都可以用,C/C++都可以,C# VB等其他语言都可以[/quote] 嗷,悲剧。我们是在linux下的
paschen 2018-03-19
  • 打赏
  • 举报
回复
引用 5 楼 bandaoyu的回复:
引用 4 楼 paschen 的回复:
你可以读到指针的值,但不同程序中这个值是指向各自程序自身的虚拟内存中,当然后你可以用ReadProcessMemory/WriteProcessMemory读写其他进程的内存
厉害,还有这种操作。ReadProcessMemory/WriteProcessMemory是C、C++都有吗? 还是只是C++
这是WINDOWS SDK,只要WINDOWS上都可以用,C/C++都可以,C# VB等其他语言都可以
paschen 2018-03-17
  • 打赏
  • 举报
回复
你可以读到指针的值,但不同程序中这个值是指向各自程序自身的虚拟内存中,当然后你可以用ReadProcessMemory/WriteProcessMemory读写其他进程的内存
自信男孩 2018-03-17
  • 打赏
  • 举报
回复
进程间通信,可以使用指针的,但是需要做好同步吧。即A进程向共享内存里写,那么B进程就不能读了。即需要加锁。
bandaoyu 2018-03-17
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢? 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话,文本文件的格式问题可参考json或xml 共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的: ·进程之间松耦合 ·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。 ·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务,只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满) ·…… “跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边, 回头是“使用共享纯文本文件进行信息交流”的岸!
//test.c 本程序演示两个进程之间通过临时文本文件交换数据实现间接调用
//A将请求数据写到文件a.txt,写完后改名为aa.txt
//B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
//A发现bb.txt存在时,读取其内容,读完后删除bb.txt
#include <io.h>
#include <stdio.h>
#include <windows.h>
int main(int argc,char **argv) {
    int d,r;
    FILE *f;
    char cmdstr[512];

    if (argc<2) {
        sprintf(cmdstr,"cmd /c \"%s\" B",argv[0]);
        WinExec(cmdstr,SW_HIDE);
        for (d=1;d<=5;d++) {//共使用1..5调用B 5次
            //A将请求数据写到文件a.txt,写完后改名为aa.txt
            f=fopen("a.txt","w");
            fprintf(f,"%d\n",d);
            fclose(f);
            rename("a.txt","aa.txt");
            printf("call with %d\n",d);
            //A发现bb.txt存在时,读取其内容,读完后删除bb.txt
            while (1) {
                Sleep(100);
                if (_access("bb.txt",0)!=-1) {
                    f=fopen("bb.txt","r");
                    fscanf(f,"%d",&r);
                    fclose(f);
                    remove("bb.txt");
                    break;
                }
            }
            printf("result:%d\n",r);
        }
        return 0;
    }
    if (argv[1][0]=='a'||argv[1][0]=='A') {//A
        for (d=1;d<=5;d++) {//共使用1..5调用B 5次
            //A将请求数据写到文件a.txt,写完后改名为aa.txt
            f=fopen("a.txt","w");
            fprintf(f,"%d\n",d);
            fclose(f);
            rename("a.txt","aa.txt");
            printf("call with %d\n",d);
            //A发现bb.txt存在时,读取其内容,读完后删除bb.txt
            while (1) {
                Sleep(100);
                if (_access("bb.txt",0)!=-1) {
                    f=fopen("bb.txt","r");
                    fscanf(f,"%d",&r);
                    fclose(f);
                    remove("bb.txt");
                    break;
                }
            }
            printf("result:%d\n",r);
        }
    } else {//B
        while (1) {
            //B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
            while (1) {
                Sleep(100);
                if (_access("aa.txt",0)!=-1) {
                    f=fopen("aa.txt","r");
                    fscanf(f,"%d",&r);
                    fclose(f);
                    r=r*10;
                    f=fopen("b.txt","w");
                    fprintf(f,"%d\n",r);
                    fclose(f);
                    remove("aa.txt");
                    rename("b.txt","bb.txt");
                    break;
                }
            }
            if (r==50) break;
        }
    }
    return 0;
}
//C:\tmp\test>test
//call with 1
//result:10
//call with 2
//result:20
//call with 3
//result:30
//call with 4
//result:40
//call with 5
//result:50
//
//C:\tmp\test>start /B test B
//
//C:\tmp\test>test A
//call with 1
//result:10
//call with 2
//result:20
//call with 3
//result:30
//call with 4
//result:40
//call with 5
//result:50
//
//C:\tmp\test>
可是这个共享内存空间还蛮大的,如果把共享内存换成共享文件,A端在写的时候多了一步打开文件,的操作,操作完之后再关闭文件。而B端还是要打开文件,实际上打开文件涉及内存的开辟操作的吧,只是将这个操作交给了系统。这样还是没有指针快。 不过老大这个回答,倒是再次提醒我用 共享文件的方式 比共享内存好,只是现在共享内存的通信方式已经存在,只能下次考虑共享文件的方案。 老大回答的真迅速,感谢!!!
赵4老师 2018-03-17
  • 打赏
  • 举报
回复
不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢? 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话,文本文件的格式问题可参考json或xml 共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的: ·进程之间松耦合 ·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。 ·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务,只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满) ·…… “跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边, 回头是“使用共享纯文本文件进行信息交流”的岸!
//test.c 本程序演示两个进程之间通过临时文本文件交换数据实现间接调用
//A将请求数据写到文件a.txt,写完后改名为aa.txt
//B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
//A发现bb.txt存在时,读取其内容,读完后删除bb.txt
#include <io.h>
#include <stdio.h>
#include <windows.h>
int main(int argc,char **argv) {
    int d,r;
    FILE *f;
    char cmdstr[512];

    if (argc<2) {
        sprintf(cmdstr,"cmd /c \"%s\" B",argv[0]);
        WinExec(cmdstr,SW_HIDE);
        for (d=1;d<=5;d++) {//共使用1..5调用B 5次
            //A将请求数据写到文件a.txt,写完后改名为aa.txt
            f=fopen("a.txt","w");
            fprintf(f,"%d\n",d);
            fclose(f);
            rename("a.txt","aa.txt");
            printf("call with %d\n",d);
            //A发现bb.txt存在时,读取其内容,读完后删除bb.txt
            while (1) {
                Sleep(100);
                if (_access("bb.txt",0)!=-1) {
                    f=fopen("bb.txt","r");
                    fscanf(f,"%d",&r);
                    fclose(f);
                    remove("bb.txt");
                    break;
                }
            }
            printf("result:%d\n",r);
        }
        return 0;
    }
    if (argv[1][0]=='a'||argv[1][0]=='A') {//A
        for (d=1;d<=5;d++) {//共使用1..5调用B 5次
            //A将请求数据写到文件a.txt,写完后改名为aa.txt
            f=fopen("a.txt","w");
            fprintf(f,"%d\n",d);
            fclose(f);
            rename("a.txt","aa.txt");
            printf("call with %d\n",d);
            //A发现bb.txt存在时,读取其内容,读完后删除bb.txt
            while (1) {
                Sleep(100);
                if (_access("bb.txt",0)!=-1) {
                    f=fopen("bb.txt","r");
                    fscanf(f,"%d",&r);
                    fclose(f);
                    remove("bb.txt");
                    break;
                }
            }
            printf("result:%d\n",r);
        }
    } else {//B
        while (1) {
            //B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
            while (1) {
                Sleep(100);
                if (_access("aa.txt",0)!=-1) {
                    f=fopen("aa.txt","r");
                    fscanf(f,"%d",&r);
                    fclose(f);
                    r=r*10;
                    f=fopen("b.txt","w");
                    fprintf(f,"%d\n",r);
                    fclose(f);
                    remove("aa.txt");
                    rename("b.txt","bb.txt");
                    break;
                }
            }
            if (r==50) break;
        }
    }
    return 0;
}
//C:\tmp\test>test
//call with 1
//result:10
//call with 2
//result:20
//call with 3
//result:30
//call with 4
//result:40
//call with 5
//result:50
//
//C:\tmp\test>start /B test B
//
//C:\tmp\test>test A
//call with 1
//result:10
//call with 2
//result:20
//call with 3
//result:30
//call with 4
//result:40
//call with 5
//result:50
//
//C:\tmp\test>

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧