的mmap
系统调用的文件说,如果该函数将失败:用户进程的有效地址空间是什么? (OS X和Linux)
MAP_FIXED被指定和地址 说法是不对齐的页面,或部分所需的地址空间的 驻留 在 用户进程的有效地址空间之外。
我找不到任何地方的文档说什么将是一个有效的地址映射。 (我有兴趣在OS X和Linux上执行此操作,理想情况下,相同的地址对于这两种操作都是有效的)。
的mmap
系统调用的文件说,如果该函数将失败:用户进程的有效地址空间是什么? (OS X和Linux)
MAP_FIXED被指定和地址 说法是不对齐的页面,或部分所需的地址空间的 驻留 在 用户进程的有效地址空间之外。
我找不到任何地方的文档说什么将是一个有效的地址映射。 (我有兴趣在OS X和Linux上执行此操作,理想情况下,相同的地址对于这两种操作都是有效的)。
Linux内核为自己保留了虚拟地址空间的一部分,以便用户空间具有(几乎)无法访问并且无法映射任何内容。你正在寻找所谓的“用户空间/内核空间拆分”。
在i386拱默认是3G/1G一个 - 用户空间变低3 GB的虚拟地址空间,核上得到1 GB,另外有2G/2G和1G/3G分裂:
config PAGE_OFFSET
hex
default 0xB0000000 if VMSPLIT_3G_OPT
default 0x80000000 if VMSPLIT_2G
default 0x78000000 if VMSPLIT_2G_OPT
default 0x40000000 if VMSPLIT_1G
default 0xC0000000
depends on X86_32
在x86_64,用户空间住在的虚拟地址空间(目前)48位的下半部分:
/*
* User space process size. 47bits minus one guard page.
*/
#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE)
这变化的基础上多种因素,其中有许多是不是你的控制之下。正如Adobriyan所说,根据操作系统的不同,您有各种固定的上限,超出这些上限是内核代码和数据所在。在32位操作系统上,通常这个上限是至少 2GB;一些操作系统提供额外的地址空间。 64位操作系统通常提供由CPU支持的虚拟地址位数(通常至少为40位地址空间)控制的上限。但也有另一些因素超出你的控制:
/proc/sys/vm/mmap_min_addr
配置的地址将被拒绝。malloc
可以自行,其放置在一定程度上任意位置这样执行mmaps,没有办法绝对是机制保障将MAP_FIXED
成功,所以它通常应避免。
我见过的唯一地方MAP_FIXED
需要的是在酒的启动代码,其储量(使用MAP_FIXED
)2G以上的所有地址,以避免混淆窗口代码不承担任何映射都不会显示出来了否定地址。当然,这是对旗帜的高度专业化使用。
如果你想这样做是为了避免处理共享内存中的偏移量,其中一个方案是包的指针在一个类来自动处理偏移:
template<typename T>
class offset_pointer {
private:
ptrdiff_t offset;
public:
typedef T value_type, *ptr_type;
typedef const T const_type, *const_ptr_type;
offset_ptr(T *p) { set(p); }
offset_ptr() { set(NULL); }
void set(T *p) {
if (p == NULL)
offset = 1;
else
offset = (char *)p - (char *)this;
}
T *get() {
if (offset == 1) return NULL;
return (T*)((char *)this + offset);
}
const T *get() const { return const_cast<offset_pointer>(this)->get(); }
T &operator*() { return *get(); }
const T &operator*() const { return *get(); }
T *operator->() { return get(); }
const T *operator->() const { return get(); }
operator T*() { return get(); }
operator const T*() const { return get(); }
offset_pointer operator=(T *p) { set(p); return *this; }
offset_pointer operator=(const offset_pointer &other) {
offset = other.offset;
return *this;
}
};
注:此是未经测试的代码,但应该给你基本的想法。
谢谢!我应该补充一点,我只对64位系统感兴趣,这就是为什么固定映射甚至是一个考虑因素,因为它似乎必须有足够的空间来避免冲突不应该太困难。 – James 2011-03-05 17:50:57
这是Linux的一个很好的答案。任何人都可以获得64位OSX的相同信息? – Quuxplusone 2012-10-10 19:10:54
回复我自己的评论:在OSX上,它似乎大致为'0x1_00000000'(从我的测试用例中运行到运行不等)直到'0x7fff_ffffffff';即内核保留低4GB的虚拟地址空间,并且虚拟地址被限制在与x86-64上的物理地址相同的48位范围内。 – Quuxplusone 2012-10-10 19:34:27