来自Linux的man shmat
逐字:
返回值
返回错误(void*)-1,并设置errno以指示错误原因.
(POSIX使用略有不同的措辞来讲述相同的内容.)
是否有任何强制性规则或定义(标准?)(void *) -1
可能不是有效地址?
Ben*_*enj 19
0xffffffff
从技术上讲,它是32位环境中的有效地址,但在大多数操作系统(当然是Linux/Windows)上都将位于地址空间的保留内核部分.这意味着在用户模式进程中将其用作错误代码是安全的,因为没有用户模式分配函数会将其作为可用地址返回.
Som*_*ude 14
为简单起见,请考虑具有16位地址空间的计算机.这台机器可以处理从0到65535的内存.在这种情况下,(void*) -1
它将与0xffff相同,即65535.虽然从技术上讲这个地址是有效的,但很少有系统可以在那里访问它们.
另一件需要考虑的事情是,几乎所有POSIX系统调用都会返回-1
错误.
正如Benj所指出的,实际上可以映射地址NULL
.例如,当您想要查看是否存在指定的映射时,可以使用此选项shmid
,在这种情况下,shmaddr
参数设置为NULL
,并且函数返回NULL
以表示共享内存存在.
Eri*_*hil 10
要直接回答这个问题,不,没有强制性规则,定义,标准或规范(void *) -1
可能不是有效地址.
(当然,没有关于内存地址的规则,定义,标准或规范是强制性的.例如,我看到人们每天走在街上而不符合C标准,但我从未见过有人因此而被捕.但是,即使我们省略了强制性部分,(void *) -1
通常也不会被普通规范用作地址.)
但是,(void *) -1
为了使shmat工作,没有必要不是有效的地址.仅仅需要成功调用shmat永远不会返回(void *) -1
并且(void *) -1
编译器支持为了测试shmat的返回值.如果满足这两个条件,那么程序总能将成功的shmat调用与不成功的shmat调用区分开来.
关于第二个条件,C标准并不保证(void *) -1
可以使用,因此POSIX在指定这是从shmat返回的错误时,隐式地要求C(或其他语言)实现来支持它.所以这是POSIX所需语言的扩展,对于编译器来说通常是一件简单的事情.
关于第一个条件,考虑我们何时可能希望shmat返回(void *) -1
成功呼叫.可以使用用户请求的地址调用shmat,也可以不使用,在这种情况下,实现选择一个地址.在任何正常的计算机体系结构中,使用多个不同值的地址有多种原因.对于shmat,最明显的是内存映射.在具有虚拟内存架构,内存映射以页为单位,和的shmat,当它映射内存段,将映射到一个页面的开始.任何偶数页大小没有倍数是(void *) -1
,因为后者是奇数,这样的shmat从来没有选择分段映射到(void *) -1
.即使的shmat没有用的页大小,它通常会使用一些其他取向,例如4,8或16个字节,因为提供对准的存储器意味着存储在该存储器的起始结构将被对齐,这导致更快的存储器访问许多处理器.
这留下了用户请求(void *) -1
作为地址的情况.这将是不寻常的,它可以工作,除非内存段是一个单字节或内存模型允许缠绕(或提出这样一个很奇怪的内存模型编译器(void *) -1
是不是在地址空间中的最后一个字节).我无法确定是否有任何POSIX系统支持这一点.然而,很明显,这基本上是无用的,除了好奇之外,没有人有任何理由去做.因此,它是安全,合理,以排除这种情况下出来的shmat的,简单地说,不支持,不这样做.