首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用户进程的有效地址空间是什么?(OS和Linux)

用户进程的有效地址空间是什么?(OS和Linux)
EN

Stack Overflow用户
提问于 2011-03-05 12:15:33
回答 2查看 2.4K关注 0票数 4

mmap系统调用文档指出,如果:

指定了MAP_FIXED,且addr参数没有对页对齐,或者所需地址空间的一部分驻留在用户进程的有效地址空间之外。

我在任何地方都找不到文件,上面写的是一个有效的地图地址。(我感兴趣的是在OS和linux上这样做,理想情况下,相同的地址对两者都是有效的。)

EN

回答 2

Stack Overflow用户

发布于 2011-03-05 13:40:24

Linux内核将部分虚拟地址空间留给用户空间(几乎)没有访问权限,并且不能映射任何内容。您正在寻找所谓的"userspace/kernelspace拆分“。

在i386 arch上,默认为3G/1G,用户空间得到3GB以下的虚拟地址空间,内核获得1GB以上的地址空间,另外还有2G/2G和1G/3G分块:

代码语言:javascript
运行
复制
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位虚拟地址空间的下半部分:

代码语言:javascript
运行
复制
/*
 * User space process size. 47bits minus one guard page.
 */
#define TASK_SIZE_MAX   ((1UL << 47) - PAGE_SIZE)
票数 7
EN

Stack Overflow用户

发布于 2011-03-05 16:41:21

这取决于许多因素,其中许多因素并不在您的控制范围之内。正如adobriyan所提到的,根据操作系统的不同,您有各种固定的上限,内核代码和数据就在这个上限之外。通常,这个上限在32位OSes上至少是2GB;一些OSes提供额外的地址空间。64位OSes通常提供一个上限,由您的CPU支持的虚拟地址位数(通常是至少40位的地址空间)控制。然而,还有其他因素超出了您的控制范围:

  • 在最近版本的linux上,在/proc/sys/vm/mmap_min_addr中配置的地址下面的mmap映射将被拒绝。
  • 您不能创建与任何现有映射重叠的映射。由于动态链接器可以自由地映射与可执行文件的固定部分不重叠的任何位置,这意味着可能会拒绝任何地址。
  • 内核可以注入其他附加映射,如系统呼叫门
  • malloc可以自己执行mmap,这些mmap放置在某种程度上任意的位置。

因此,没有办法绝对保证MAP_FIXED会成功,因此通常应该避免它。

我所看到的唯一需要MAP_FIXED的地方是在葡萄酒启动代码中,它保留(使用MAP_FIXED) 2G以上的所有地址,以避免混淆windows代码,因为这些代码假定没有映射就会出现负地址。当然,这是对国旗的高度专业化的使用。

如果您试图这样做,以避免不得不处理共享内存中的偏移量,一种选择是将指针包装在类中以自动处理偏移:

代码语言:javascript
运行
复制
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;
        }
};

注意:这是未经测试的代码,但应该给您一个基本的想法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5203748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档