os 虚拟内存

2024-08-24 15:28
文章标签 虚拟内存 os

本文主要是介绍os 虚拟内存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

虚拟内存不仅能隔离进程,还能提高内存利用率,请解释虚拟内存如何提高内存利用率???

虚拟内存(Virtual Memory)通过以下几个机制来提高内存利用率:

1. 内存分页(Paging)

虚拟内存将物理内存划分为固定大小的块,称为页框(page frame),同时将进程的虚拟内存空间划分为同样大小的页(page)。虚拟内存系统通过页表(page table)将虚拟页映射到物理页框。由于每个进程只需在物理内存中保留当前使用的页面,其余页面可以留在磁盘上,这就避免了将整个进程加载到内存中,从而减少了物理内存的使用。

2. 按需调页(Demand Paging)

按需调页是指在进程执行时,只有在需要访问某个页面时才将该页面从磁盘加载到内存中。未被访问的页面则不占用物理内存。这种策略避免了不必要的内存占用,使得物理内存只用于活跃的页面,从而提高了内存利用率。

3. 页交换(Swapping)

当物理内存不足时,操作系统可以将暂时不活跃的页面移出物理内存,存放到磁盘的交换空间中。这种机制允许更多的进程共享有限的物理内存,通过动态调整每个进程的物理内存占用,优化了内存的利用效率。

4. 共享内存(Shared Memory)

在某些情况下,不同进程可以共享相同的内存页。比如,多个进程运行同一个程序时,操作系统可以让它们共享相同的只读代码段。这减少了冗余数据的内存占用,进一步提高了内存利用率。

5. 内存映射文件(Memory-Mapped Files)

通过内存映射文件,文件的内容可以直接映射到进程的虚拟内存空间中。这种方式避免了将文件内容加载到物理内存中的需要,从而节省了内存。只有当进程实际访问这些文件内容时,相应的页面才会被加载到物理内存。

总结

虚拟内存通过以上机制,使得操作系统能够有效地管理物理内存,减少不必要的内存占用,支持多个进程并发运行,从而显著提高内存利用率。这种内存管理方式不仅优化了系统性能,还提供了进程隔离和稳定性。


每个进程的虚拟地址空间中,内核空间的地址经过页表翻译后,都是指向同一片物理地址吗??

是的,在大多数操作系统中,每个进程的虚拟地址空间都包含一个内核空间,这个内核空间的地址经过页表翻译后,通常指向相同的物理内存区域。

具体解释

1. 虚拟地址空间的划分

典型的操作系统(如Linux)将每个进程的虚拟地址空间划分为两部分:

  • 用户空间(User Space):用于运行用户态应用程序。不同的进程有各自独立的用户空间。
  • 内核空间(Kernel Space):用于操作系统内核代码和内核态的数据结构。这个部分在所有进程中是相同的。
2. 页表翻译

每个进程都有自己的页表,负责将虚拟地址映射到物理地址。对于用户空间,页表会将进程的虚拟地址映射到不同的物理内存区域,每个进程的用户空间地址到物理地址的映射通常是独立的。

但是对于内核空间,大多数操作系统的设计是让内核空间的虚拟地址映射到相同的物理地址。因此,内核态的代码和数据在所有进程的虚拟地址空间中都是相同的,且都映射到相同的物理内存区域。

3. 原因和好处
  • 一致性:这种设计使得内核代码在不同的进程上下文中可以使用相同的地址访问相同的物理资源,简化了内核开发和调试。
  • 安全性:虽然内核空间的虚拟地址在所有进程中都是相同的,但普通用户态进程无法直接访问这些地址,只有内核态代码才能操作内核空间,从而保护了系统的稳定性和安全性。
4. 实际示例

在x86架构的Linux系统中,32位的虚拟地址空间通常被划分为下半部分(0x00000000到0xBFFFFFFF)为用户空间,上半部分(0xC0000000到0xFFFFFFFF)为内核空间。对于所有进程,0xC0000000以上的虚拟地址都映射到相同的物理地址,这些地址被用于访问内核态的代码和数据。

总结

因此,确实,每个进程的虚拟地址空间中的内核空间的虚拟地址经过页表翻译后,通常会指向相同的物理地址。这种设计既保证了内核的一致性,又确保了系统的安全性和稳定性。

在这里插入图片描述


在 4GB 物理内存的机器上,申请 8G 内存会怎么样?
在一台只有 4GB 物理内存的机器上,如果一个进程试图申请 8GB 的内存,操作系统会利用虚拟内存技术来处理这个请求。这可能会导致以下几种情况:

1. 内存分配成功

操作系统通常不会立即分配物理内存,而是分配虚拟内存地址空间。这意味着即使物理内存不足,进程仍然可能成功申请到 8GB 的虚拟内存。这是因为虚拟内存空间可以大于物理内存。操作系统通过分页机制来管理虚拟内存,并使用磁盘上的交换空间(swap space)来弥补物理内存的不足。

2. 实际内存使用与分配不同

即使申请了 8GB 的虚拟内存,进程只有在实际使用这些内存时(即访问这段内存)才会触发操作系统将其映射到物理内存。对于那些未实际访问的部分,操作系统不会为其分配物理内存。因此,如果进程实际使用的内存远小于 8GB,那么物理内存的占用量也会较小。

3. 使用交换空间

当进程实际使用的内存超出物理内存的容量时,操作系统会将不常用的内存页面交换到磁盘上的交换空间中,以腾出物理内存给需要的页面。这种机制允许系统在物理内存不足的情况下,继续支持更大的内存需求。

4. 性能下降

使用交换空间会导致性能下降,因为磁盘的访问速度远低于物理内存。随着越来越多的内存页面被交换到磁盘上,系统会变得非常缓慢,可能出现频繁的磁盘I/O操作,甚至导致“交换颠簸”(thrashing),即系统花费大量时间在内存页面的交换上,而无法有效执行任务。

5. 内存不足错误

如果操作系统的交换空间用尽,或者系统无法为进程分配所需的内存资源,内存分配操作可能会失败。此时,进程可能会收到std::bad_alloc(C++)或OutOfMemoryError(Java)等错误,表明内存分配失败。

6. OOM(Out Of Memory)杀手

在Linux等操作系统中,当系统内存耗尽时,内核可能会启动OOM杀手,选择性地终止某些进程以释放内存,确保系统的其余部分能够继续运行。如果你的进程占用了大量内存且系统内存不足,它可能会成为OOM杀手的目标,从而被强制终止。

总结

在4GB物理内存的机器上申请8GB内存,操作系统会利用虚拟内存和交换空间技术来处理请求,但这可能导致显著的性能下降,甚至内存分配失败或进程被终止。因此,在有限的物理内存环境中,申请远超出物理内存容量的大量内存通常不是一个好的做法。

信号量(Semaphore)和条件变量(Condition Variable)都是用于线程同步的机制,但它们的设计目的和使用场景有所不同。以下是它们的主要区别:

1. 用途与概念

  • 信号量(Semaphore)

    • 计数器:信号量是一个计数器,用于控制对共享资源的访问。它可以用来限制同时访问某个资源的线程数量,或者控制某些操作的顺序。
    • 信号量的类型
      • 二元信号量(Binary Semaphore):也称为互斥量(Mutex),只有两个值,0或1,用于实现互斥锁。
      • 计数信号量(Counting Semaphore):可以有多个值,用于控制对有限资源的访问。例如,一个计数信号量可以用于限制最多有N个线程同时访问某个资源。
    • 操作:信号量主要通过P()(wait)和V()(signal)操作实现。
      • P():将信号量的值减1,如果结果为负,则阻塞当前线程。
      • V():将信号量的值加1,如果有等待的线程,则唤醒其中一个。
  • 条件变量(Condition Variable)

    • 条件同步:条件变量用于线程之间的条件同步。它允许线程等待某个条件成立时再继续执行。
    • 等待和通知:条件变量通常与互斥锁配合使用。线程可以在条件变量上等待,直到另一个线程发出信号通知条件成立。
    • 操作
      • wait():释放关联的互斥锁并进入等待状态,直到条件变量被通知(通常由另一个线程调用signal()broadcast())。
      • signal():通知一个等待该条件的线程,使其从等待状态转为可运行状态。
      • broadcast():通知所有等待该条件的线程。

2. 使用场景

  • 信号量的使用场景

    • 控制对共享资源的访问,例如限制同时访问某个资源的线程数量。
    • 用于实现生产者-消费者问题、读者-写者问题等经典同步问题。
    • 可以用于实现线程间的顺序控制。
  • 条件变量的使用场景

    • 用于实现复杂的条件同步,例如等待某个特定条件成立后才执行某个操作。
    • 常用于实现基于条件的等待机制,类似于“等待/通知”模式。
    • 适用于那些需要通过检查共享状态并等待特定条件成立的线程间同步问题。

3. 工作机制

  • 信号量:信号量的值控制着资源的使用,当信号量的值为正时,表示有足够的资源可用;当信号量的值为负时,表示线程需要等待。
  • 条件变量:条件变量并不直接控制资源,而是用于等待某个条件的发生。条件变量与互斥锁配合,线程在等待条件时会释放锁,从而允许其他线程改变条件并通知等待的线程。

4. 适用场景的总结

  • 信号量更适合于控制资源的并发访问,例如限制线程访问共享资源的数量。
  • 条件变量更适合在需要等待某个条件发生时使用,特别是当需要线程之间进行复杂的条件协调时。

总结

信号量和条件变量都是重要的线程同步工具,但它们解决的问题不同。信号量用于管理资源的并发访问,而条件变量则用于实现条件等待和线程间的通知。选择哪一种同步机制取决于具体的应用场景和需求。

这篇关于os 虚拟内存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1102867

相关文章

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.B

一个bug日志 FATAL EXCEPTION: main03-25 14:24:07.724: E/AndroidRuntime(4135): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.syyx.jingubang.ky/com.anguotech.android.activity.Init

【python 文件操作】shutil模块和OS模块

总结 os包: rmdir, mkdir, listdir, remove, rename, chmod, chown, stat, symlink shutil包: copy, move os包 os包包括各种各样的函数,以实现操作系统的许多功能。这个包非常庞杂。os包的一些命令就是用于文件管理。我们这里列出最常用的: mkdir( path ) 创建新目录,path为一个字符串,表示新

Linux进程初识:OS基础、fork函数创建进程、进程排队和进程状态讲解

目录 1、冯诺伊曼体系结构 问题一:为什么在体系结构中存在存储器(内存)? 存储单元总结: 问题二:为什么程序在运行的时候,必须把程序先加载到内存? 问题三:请解释,从你登录上qq开始和某位朋友聊天开始,数据的流动过程。 2、操作系统 2.1操作系统的概念: 我们首先要明白什么是管理: 2.2为什么要有操作系统? 2.3操作系统如何保证稳定和安全呢?(利用系统调用函数解决)

Beyond Compare4.2.4 64位OS最新密钥

亲测可用,拿来主义 6TTCoWi2N0Pv+o2HGfqUpZfuaMhtf2zX0u1OuNeqTYkKKWh-CKwBWkPUG3+CiAQ2q4MNPbf0t8+gmPdo+Vyw64aU-zuQQt9d7Q6EcJ+T42by0E+kxf+q3QLs40H+RD3h5OLjFGpxClodRnTCNoAM39xsWm2aHZI0Z9KdXzLo1fo1OdNlaptoK17SsxNK-

OS_程序的装入与链接

2024.09.05:操作系统程序的装入与链接学习笔记 第12节 程序的装入与链接 2.1 程序的装入2.1.1 绝对装入方式2.1.2 可重定位装入方式(静态重定位)2.1.3 动态运行时装入方式(动态重定位) 2.2 程序的链接2.2.1 静态链接方式2.2.2 装入时动态链接2.2.3 运行时动态链接 操作系统的第三章内存管理,在学习正式的管理策略之前,我们知

[linux命令] 随笔集 center OS 7 蛋疼的改动 一个菜鸟的奋斗shit~~~

2018年7月24日17:22:30 虚拟机查看ip地址  center OS 7  最小化安装. 查看ip地址:使用ifconfig已经不适用了 , 需要使用 ip addr 可以看到 关闭防火墙命令也不是 stop iptables.service 命令了,  看下百度经验吧7 关闭防火墙系列命令 关闭防火墙: systemctl stop firewalld.service

内存管理篇-21 虚拟内存管理:线性映射区

1.线性映射区的定义         这部分讲线性映射区的内容。一般老的嵌入式平台,它内存很小只有几百兆,都会直接把整个物理内存映射到线性映射区了,只有当物理内存大于1GB以上,线性映射区无法cover的时候就把剩下的放到高端内存。所以这个区域是最简单的。         线性映射区一般是指内核空间的某个部分,直接映射到低端内存的区域。并且他们之间是线性映射的。         PAGE_O

苹果系统升级 为 OS X EL Capitan 后安装 cocoapods

1.移除现有Ruby默认源 $gem sources --remove https://rubygems.org/ 2.使用新的源 $gem sources -a https://ruby.taobao.org/ 3.验证新源是否替换成功 $gem sources -l 4.安装CocoaPods  $sudo gem install -n /usr/local/bi

解密虚拟内存0x400000以下的地方

一. 前言   最近看CSAPP时,对以前没有仔细注意的一处知识盲区产生了兴趣,所以进行了深入研究,并写下此文一记录。 二. 问题   二话不说直接上图。下图是CSAPP第七章的虚拟内存分析图。书中提到 在X86-64位Linux系统中,代码段总是从地址0x400000处开始,后面是数据段。堆在数据段之后,通过调用malloc向上增长…   但是0X400000以下呢?为什么没有

XCode开发OS X时多个版本TARGETS的控制

XCode开发OS X时多个版本TARGETS的控制 主要有以下步骤: 1.选择TARGETS的一个,然后Right Click->Duplicate(复制) 生成一个copy 2.然后修改这个copy,click 2次,就可以修改。 3.然后在STOP旁边的 编译目标点击,会出现Manager 表格,打开,点击刚才的copy,修改名称,最好和上面一致,这样容易辨认。 4.修改第一个TA