umap格式文件|C内存共享进程通信范例

Ⅰ C内存共享进程通信范例

mmap()范例 下面将给出使用mmap()的两个范例:范例1给出两个进程通过映射普通文件实现共享内存通信;范例2给出父子进程通过匿名映射实现共享内存。系统调用mmap()有许多有趣的地方,下面是通过mmap()映射普通文件实现进程间的通信的范例,我们通过该范例来说明mmap()实现共享内存的特点及注意事项。范例1:两个进程通过映射普通文件实现共享内存通信范例1包含两个子程序:map_normalfile1.c及map_normalfile2.c。编译两个程序,可执行文件分别为map_normalfile1及map_normalfile2。两个程序通过命令行参数指定同一个文件来实现共享内存方式的进程间通信。map_normalfile2试图打开命令行参数指定的一个普通文件,把该文件映射到进程的地址空间,并对映射后的地址空间进行写操作。map_normalfile1把命令行参数指定的文件映射到进程地址空间,然后对映射后的地址空间执行读操作。这样,两个进程通过命令行参数指定同一个文件来实现共享内存方式的进程间通信。下面是两个程序代码:/*————-map_normalfile1.c———–*/#include <sys/mman.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>typedef struct{ char name[4]; int age;}people;main(int argc, char** argv) // map a normal file as shared mem:{ int fd,i; people *p_map; char temp; fd=open(argv[1],O_CREAT|O_RDWR|O_TRUNC,00777); lseek(fd,sizeof(people)*5-1,SEEK_SET); write(fd,"",1); p_map = (people*) mmap( NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0 ); close( fd ); temp = 'a'; for(i=0; i<10; i++) { temp += 1; memcpy( ( *(p_map+i) ).name, &temp,2 ); ( *(p_map+i) ).age = 20+i; } printf(" initialize over \n "); sleep(10); munmap( p_map, sizeof(people)*10 ); printf( "umap ok \n" );}/*————-map_normalfile2.c———–*/#include <sys/mman.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>typedef struct{ char name[4]; int age;}people;main(int argc, char** argv) // map a normal file as shared mem:{ int fd,i; people *p_map; fd=open( argv[1],O_CREAT|O_RDWR,00777 ); p_map = (people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); for(i = 0;i<10;i++) { printf( "name: %s age %d;\n",(*(p_map+i)).name, (*(p_map+i)).age ); } munmap( p_map,sizeof(people)*10 );}map_normalfile1.c首先定义了一个people数据结构,(在这里采用数据结构的方式是因为,共享内存区的数据往往是有固定格式的,这由通信的各个进程决定,采用结构的方式有普遍代表性)。map_normfile1首先打开或创建一个文件,并把文件的长度设置为5个people结构大小。然后从mmap()的返回地址开始,设置了10个people结构。然后,进程睡眠10秒钟,等待其他进程映射同一个文件,最后解除映射。map_normfile2.c只是简单的映射一个文件,并以people数据结构的格式从mmap()返回的地址处读取10个people结构,并输出读取的值,然后解除映射。分别把两个程序编译成可执行文件map_normalfile1和map_normalfile2后,在一个终端上先运行./map_normalfile2 /tmp/test_shm,程序输出结果如下:initialize overumap ok在map_normalfile1输出initialize over 之后,输出umap ok之前,在另一个终端上运行map_normalfile2 /tmp/test_shm,将会产生如下输出(为了节省空间,输出结果为稍作整理后的结果):name: b age 20; name: c age 21; name: d age 22; name: e age 23; name: f age 24;name: g age 25; name: h age 26; name: I age 27; name: j age 28; name: k age 29;在map_normalfile1 输出umap ok后,运行map_normalfile2则输出如下结果:name: b age 20; name: c age 21; name: d age 22; name: e age 23; name: f age 24;name: age 0; name: age 0; name: age 0; name: age 0; name: age 0;从程序的运行结果中可以得出的结论1、 最终被映射文件的内容的长度不会超过文件本身的初始大小,即映射不能改变文件的大小;2、 可以用于进程通信的有效地址空间大小大体上受限于被映射文件的大小,但不完全受限于文件大小。打开文件被截短为5个people结构大小,而在map_normalfile1中初始化了10个people数据结构,在恰当时候(map_normalfile1输出initialize over 之后,输出umap ok之前)调用map_normalfile2会发现map_normalfile2将输出全部10个people结构的值,后面将给出详细讨论。 注:在linux中,内存的保护是以页为基本单位的,即使被映射文件只有一个字节大小,内核也会为映射分配一个页面大小的内存。当被映射文件小于一个页面大小时,进程可以对从mmap()返回地址开始的一个页面大小进行访问,而不会出错;但是,如果对一个页面以外的地址空间进行访问,则导致错误发生,后面将进一步描述。因此,可用于进程间通信的有效地址空间大小不会超过文件大小及一个页面大小的和。3、 文件一旦被映射后,调用mmap()的进程对返回地址的访问是对某一内存区域的访问,暂时脱离了磁盘上文件的影响。所有对mmap()返回地址空间的操作只在内存中有意义,只有在调用了munmap()后或者msync()时,才把内存中的相应内容写回磁盘文件,所写内容仍然不能超过文件的大小。范例2:父子进程通过匿名映射实现共享内存#include <sys/mman.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>typedef struct{ char name[4]; int age;}people;main(int argc, char** argv){ int i; people *p_map; char temp; p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); if(fork() == 0) { sleep(2); for(i = 0;i<5;i++) printf("child read: the %d people's age is %d\n",i+1,(*(p_map+i)).age); (*p_map).age = 100; munmap(p_map,sizeof(people)*10); //实际上,进程终止时,会自动解除映射。 exit(); } temp = 'a'; for(i = 0;i<5;i++) { temp += 1; memcpy((*(p_map+i)).name, &temp,2); (*(p_map+i)).age=20+i; } sleep(5); printf( "parent read: the first people,s age is %d\n",(*p_map).age ); printf("umap\n"); munmap( p_map,sizeof(people)*10 ); printf( "umap ok\n" );}考察程序的输出结果,体会父子进程匿名共享内存:child read: the 1 people's age is 20child read: the 2 people's age is 21child read: the 3 people's age is 22child read: the 4 people's age is 23child read: the 5 people's age is 24parent read: the first people,s age is 100umapumap ok回页首 四、对mmap()返回地址的访问前面对范例运行结构的讨论中已经提到,linux采用的是页式管理机制。对于用mmap()映射普通文件来说,进程会在自己的地址空间新增一块空间,空间大小由mmap()的len参数指定,注意,进程并不一定能够对全部新增空间都能进行有效访问。进程能够访问的有效地址大小取决于文件被映射部分的大小。简单的说,能够容纳文件被映射部分大小的最少页面个数决定了进程从mmap()返回的地址开始,能够有效访问的地址空间大小。超过这个空间大小,内核会根据超过的严重程度返回发送不同的信号给进程。可用如下图示说明:注意:文件被映射部分而不是整个文件决定了进程能够访问的空间大小,另外,如果指定文件的偏移部分,一定要注意为页面大小的整数倍。下面是对进程映射地址空间的访问范例:#include <sys/mman.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>typedef struct{ char name[4]; int age;}people;main(int argc, char** argv){ int fd,i; int pagesize,offset; people *p_map; pagesize = sysconf(_SC_PAGESIZE); printf("pagesize is %d\n",pagesize); fd = open(argv[1],O_CREAT|O_RDWR|O_TRUNC,00777); lseek(fd,pagesize*2-100,SEEK_SET); write(fd,"",1); offset = 0; //此处offset = 0编译成版本1;offset = pagesize编译成版本2 p_map = (people*)mmap(NULL,pagesize*3,PROT_READ|PROT_WRITE,MAP_SHARED,fd,offset); close(fd); for(i = 1; i<10; i++) { (*(p_map+pagesize/sizeof(people)*i-2)).age = 100; printf("access page %d over\n",i); (*(p_map+pagesize/sizeof(people)*i-1)).age = 100; printf("access page %d edge over, now begin to access page %d\n",i, i+1); (*(p_map+pagesize/sizeof(people)*i)).age = 100; printf("access page %d over\n",i+1); } munmap(p_map,sizeof(people)*10);}如程序中所注释的那样,把程序编译成两个版本,两个版本主要体现在文件被映射部分的大小不同。文件的大小介于一个页面与两个页面之间(大小为:pagesize*2-99),版本1的被映射部分是整个文件,版本2的文件被映射部分是文件大小减去一个页面后的剩余部分,不到一个页面大小(大小为:pagesize-99)。程序中试图访问每一个页面边界,两个版本都试图在进程空间中映射pagesize*3的字节数。版本1的输出结果如下:pagesize is 4096access page 1 overaccess page 1 edge over, now begin to access page 2access page 2 overaccess page 2 overaccess page 2 edge over, now begin to access page 3Bus error //被映射文件在进程空间中覆盖了两个页面,此时,进程试图访问第三个页面版本2的输出结果如下:pagesize is 4096access page 1 overaccess page 1 edge over, now begin to access page 2Bus error //被映射文件在进程空间中覆盖了一个页面,此时,进程试图访问第二个页面结论:采用系统调用mmap()实现进程间通信是很方便的,在应用层上接口非常简洁。内部实现机制区涉及到了linux存储管理以及文件系统等方面的内容,可以参考一下相关重要数据结构来加深理解。在本专题的后面部分,将介绍系统v共享内存的实现。参考资料 [1] Understanding the Linux Kernel, 2nd Edition, By Daniel P. Bovet, Marco Cesati , 对各主题阐述得重点突出,脉络清晰。[2] UNIX网络编程第二卷:进程间通信,作者:W.Richard Stevens,译者:杨继张,清华大学出版社。对mmap()有详细阐述。[3] Linux内核源代码情景分析(上),毛德操、胡希明著,浙江大学出版社,给出了mmap()相关的源代码分析。[4]mmap()手册

Ⅱ UE4对象系统_序列化和uasset文件格式

虚幻的序列化这块是个人比较喜欢的技术点,个人在工作中也山寨了个简化版,UE4延续了UE3的序列化方案。它使用了访问者模式(Vistor Pattern),将序列化的存档接口抽象化,其中FArchive为访问者, 其它实现了void Serialize( FArchive& Ar )接口的类为被访问者。FArchive可以是磁盘文件访问, 内存统计,对象统计等功能。 FArchive的类继承体系如下: 定义接口如下: 通过重载operater <<来实现对数据的访问。 下面为调试时的几张堆栈图: UE中使用统一的格式存储资源(uasset, umap),每个uasset对应一个包(package),存储一个UPackage对象时,会将该包下的所有对象都存到uasset中。UE的uasset文件格式很像Windows下的DLL文件格式(PE格式),并且使用起来神似(下一节分析Linker)。 导入表条目FObjectImport 导出表的条目FObjectExport

Ⅲ umap后啜是什么文件需要用什么打开

第一,UMAP是游戏自己定义的私有文件类型,并不存在公开的打开方式,如果你懂得解包技术,又知道这个游戏是用什么方式封包的,或者可以试试。第二,一般的网游都有文件保护的,你的想法基本是不可能实现,要黑白色也简单,在显卡驱动里设置一下就行了,但网游不加载地图的话,肯定进不去。

Ⅳ UE4基础知识总结

一、游戏架构 1.Pawn 是作为世界中的一个 “代理”的Actor。Pawn可以由控制器处理,它们可以轻松地接受输入,并且可以执行各种各样的类似于玩家的动作。 2.Character是类人的Pawn。它默认包含一个用于碰撞的CapsuleComponent(胶囊体组件)和CharacterMovementComponent (角色运动组件)它可以进行基本的拟人运动,      它可以平滑地在网格上复制运动,并且它具有一些动画相关的功能。 3.Controller是负责管理Pawn的Actor,分为AIController和PlayerController。其中PlayerController(玩家控制器)是Pawn和控制它的人类玩家间的接口。PlayerController本质上代表了人类玩家的意愿。      AIController正如其名,是控制Pawn的一个仿真“意愿”。 4.HUD 是一种“平头显示信息”,或者说是二维的屏幕显示信息,在很多游戏中都很常见。PlayerCameraManager是玩家的眼睛,管理玩家如何表现。每个PlayerController一般也具有一个这样的类。 5.游戏这个概念划分为两个类。Game Mode 和 Game State 是游戏的定义,包括像游戏规则及获胜条件这样的内容。      其中Game Mode仅存在于服务器上。它一般在游戏过程中不会有太多数据改变,并且它一定不应该具有客户端需要的临时数据。      GameState 包含了游戏状态,它存在于服务器和所有客户端上,可以自由地进行复制来保持同步。      PlayerState是游戏中的一个参与者的状态,比如人类玩家或者模拟人类玩家的机器人。所有玩家的PlayerStates在所有机器上都存在,并且可以自由地进行复制来保持同步。 6.总结:一个游戏由GameMode和GameState构成。加入游戏的人类玩家同PlayerController相关联。      这些PlayerController允许玩家在游戏中占有pawn,以便它们在游戏中有物理表示。      PlayerController也为玩家提供了输入控制、平头显示信息或HUD、 及处理相机视图的PlayerCameraManager。 二、虚幻项目 1.项目的所有内容均包含在项目目录中。可创建任意数量的项目,但每个均为自含式。使用虚幻引擎的 项目浏览器(Project Browser)进行创建新项目将设置必要的项目框架,      如目录结构和可在编辑器中打开的虚幻项目文件([ProjectName].uproject)。 2.项目所包含的资源作为 .uasset 文件存储在 Content 文件夹中。这些资源包括材质、静态和骨骼网格体、蓝图、声音提示,以及纹理。它们是可重复使用的参考物质和模板,可被项目中的对象调用。 3.项目中还包括关卡。关卡通常被称作地图,作为 .umap 文件存储在 Content 文件夹中。在虚幻编辑器中,每次可针对一个关卡进行操作,关卡将显示在视口中。 4.关卡中可放置Actor。Actor 是一个游戏性实体,(通常)包含一个或多个组件。


赞 (0)