ACE

    技术2022-05-19  20

          ACE太大了,学习的过程充满了坎坷,我想还是从基础开始吧,撇开ACE作为网络开发库的初衷不说,ACE也是学习操作系统相关知识的良好资源,良好的跨平台性使得它必须封装操作系统提供的各种应用程序接口,所以学习ACE基础就当作是复习操作系统吧,慢慢积累,相信总有一天我能站在平流层的高度来一睹ACE的全貌。内存映射是IPC中的一种,不过其似乎作为进程通信的一种手段在实际用途中似乎用的并不多,大多数人将其作为一种简洁高效率操作文件的手段来使用。通过strace跟踪Linux各种命令的运行可以发现里面有大量的mmap调用。作为一种低层次的系统调用,Linux和Windows下的使用方式当然不同,但是ACE提供ACE_Mem_Map这个类来统一各平台的差异性,在学习ACE的过程中,我现在都不喜欢直接使用操作系统的API了,什么都想在前面加上一个"ACE_OS::",这样我内心就会觉得稳妥多了。

           下面这个例子同样也是我从ACE源码包中tests目录中Mem_Map_Test测试代码总结提取出来的,加上了点自己的想法和注释,这是我喜欢的学习方式。写这段代码遇到一个问题浪费了点时间琢磨,我修改了映射到内存中的数据,然后想将修改保存到文件中,调用sync方法,数据却怎么都没有保存到硬盘中,查了查资料才找到问题的原因,原来作为IPC的一种,内存映射有一个选项用于设置修改仅对本进程有效(ACE_MAP_PRIVATE)还是对于共享有效(MAP_SHARED)。

            ACE_Mem_Map::map有三个重载函数,其中一个如下:

      /// Map a file specified by @a filename.  int map (const ACE_TCHAR *filename,           size_t length = static_cast<size_t> (-1),           int flags = O_RDWR | O_CREAT,           mode_t mode = ACE_DEFAULT_FILE_PERMS,           int prot = PROT_RDWR,           int share = ACE_MAP_PRIVATE,           void *addr = 0,           ACE_OFF_T offset = 0,           LPSECURITY_ATTRIBUTES sa = 0);

    可以看出share默认等于,这样修改就不能保存在硬盘中,此处传递MAP_SHARED给map函数就好了,但是由于C++不支持"int share = MAP_SHARED"这样传递参数(python是支持的),所以必须将前面的默认参数都填起,这一点在拥有众多默认参数的函数上感觉很糟糕,希望未来的C++能添加这一特性。另外一个问题是我不能在这个文件后面添加一些数据,操作时没有错误,但是同步后,修改不会被保存到硬盘中,这一点有待于进一步研究。其实是可以附加数据的,只不过ACE_Mem_Map::size返回的可不是文件中字符的个数,它的默认值似乎是1000,如果使用mmap.addr()+mmap.size()偏移想在文件的最后位置附加数据就不能被保存到硬盘中,可能是sync默认只保存1000个字节吧。

    #include "ace/Mem_Map.h"#include "ace/ACE.h"#include "ace/OS_NS_string.h"#include "ace/OS_NS_unistd.h"#include "ace/OS_NS_fcntl.h"#include "ace/OS_Memory.h"#include "ace/Log_Msg.h"

    int main(int, char**){ const char filename[] = "memmap.txt";

     //注意O_TRUNC这个选项会将文件清空 ACE_HANDLE file_handle = ACE_OS::open (filename,          O_RDWR | O_CREAT | O_TRUNC,          ACE_DEFAULT_FILE_PERMS);

     if (file_handle  == ACE_INVALID_HANDLE) {  ACE_ERROR_RETURN ((LM_ERROR,       ACE_TEXT ("Open failed for %s/n"),       filename),      -1); } else {  ACE_DEBUG((LM_DEBUG, "Open %s successfully/n", filename)); }

     char buf[128] = "ecy fu";

     //往文件中写数据,如果文件为空然后就将其映射到内存中会导致运行时异常 ACE_OS::write(file_handle, buf, ACE_OS::strlen(buf));

     //关闭文件 ACE_OS::close (file_handle);

     ACE_Mem_Map mmap;

     //注意参数的填写哦 if (mmap.map (filename, -1, O_RDWR, ACE_DEFAULT_FILE_PERMS, PROT_RDWR, int share = MAP_SHARED) == -1)  ACE_ERROR_RETURN ((LM_ERROR,        ACE_TEXT ("%n: %p %s/n%a"),        ACE_TEXT ("mmap"),        filename),       -1);

     //获取开始指针,这样就可以通过指针来操作文件的内容了,显得特别方便 char* ptr = (char *) mmap.addr ();

     ACE_DEBUG((LM_DEBUG, "read from file: /n"));

     for(int i =0; i < mmap.size(); ++i, ++ptr)  ACE_DEBUG((LM_DEBUG, "%c", *ptr));

     ACE_DEBUG((LM_DEBUG, "/n"));

     //修改前三个字符 ptr = (char *) mmap.addr (); *ptr = ':'; *++ptr = '-'; *++ptr = ')';

     //将内存中的修改同步到硬盘文件中 if (mmap.sync() == -1)  ACE_DEBUG((LM_DEBUG, "sync error!!!/n"));

     ptr = (char *) mmap.addr ();

     ACE_DEBUG((LM_DEBUG, "read from file: /n"));

     for(int i =0; i < mmap.size(); ++i, ++ptr)  ACE_DEBUG((LM_DEBUG, "%c", *ptr));

     ACE_DEBUG((LM_DEBUG, "/n"));

     //将数据同步到文件中 if (mmap.sync() == -1)  ACE_DEBUG((LM_DEBUG, "sync error!!!/n"));

     mmap.close();

     //ACE_OS::unlink(filename);

     return 0;}


    最新回复(0)