1

我正在做的是:

shmget(shm_key, shm_size, 0666 | IPC_CREAT);(当然附上它)

而且我已经将大小设置为正好 12 字节但是当我尝试类似的东西时:

sprintf(shm_ptr, "Imagine about 200-300 characters here\n");

它似乎在零问题或警告的情况下正常工作,为了检查这一点,我尝试从一个完全不同的进程(我 fork 并执行第一个进程)中读取它,果然

printf("%s", shm_ptr);

打印该段中的消息,它应该是 12 字节。System V IPC 是否应该是这样的,并且没有解决该问题的方法?如果是这样,为什么首先要设置尺寸?

感谢您的时间和提前回答。

4

3 回答 3

2

没有什么能阻止你,但规范不保证这种情况下的任何特定行为。

实际上,内存区域的实际大小将四舍五入到系统特定的页面大小。这使得访问比请求更多的内存成为可能,但可能会产生后果。例如,内存清理程序可能会将其视为错误。

这适用于所有内存映射,包括使用mmap.

现在,为什么你需要访问超出请求区域的内存?如果您需要更多内存,只需请求更多。让内存清理器不会因为意外行为而发疯是一件非常有用的事情。除此之外,我认为这不会产生任何后果,至少我无法想出任何atm。

编辑:如果您想在代码中查找访问错误,可以在内存块的末尾放置一个“保护页”。只需分配一页额外的内存并用于mprotect将其访问权限更改为PROT_NONE. 这样,如果您超出映射范围(但不超过 1 页),您将获得段错误。

于 2017-11-24T20:01:33.147 回答
1

MMU硬件正在固定页面大小,因此您的虚拟地址空间以 4 KB的页面组织。

任何虚拟地址段(甚至是来自 SysV IPCMEM 的)都是该页面大小的倍数。使用sysconf(3)PAGESIZEgetpagesize(2)来 获取它。

(Linux 也有“大页面”,例如 x86 上的 1Mbytes)。

顺便说一句,阅读proc(5)并考虑使用/proc/self/mapsor/proc/1234/maps用于 pid 1234 的进程来查询该进程的虚拟地址空间....

PS。更喜欢使用shm_overview(7)

于 2017-11-24T19:59:12.173 回答
1

没有什么能阻止您尝试使用该地区以外的地址。但也没有任何东西可以保护您免受可能的后果。

它可能只是表现得好像该区域更大。它可能会出现段错误(或您平台上的任何等效项)。它可能会覆盖随机堆内存,导致您的程序以不可预知的方式行为异常。它可能会做任何事情

C 不提供监护人来保证您遵守规则。守护者很昂贵,如果你想要一个,你必须自己付费(通过编写守护代码,并在必要时执行它)。

于 2017-11-24T20:05:36.813 回答