这三者主要面向的对象不一样吧,jetsonnano主要用于机器学习、人工智能等方面,树莓派主要用于计算机编程教育,比起前两者STM32的应用范围更广一些(也可能是前两者我不是很熟悉的缘故)。
STM32可以跑 *** 作系统,但是不能跑Linux,因为其属于Cortex-M系列不带MMU。另外,Cortex-A系列可以跑Linux,因为它带MMU。
内存管理
*** 作系统对内存的划分和动态分配,就是内存管理的概念。有效的内存管理在多道程序设计中非常重要,不仅方便用户使用存储器、提高内存利用率,还可以通过虚拟技术从逻辑上扩充存储器。内存管理的功能有:
内存空间的分配与回收
地址转换:在多道程序环境下,程序中的逻辑地址与内存中的物理地址不可能一致,因此存储管理必须提供地址变换功能,把逻辑地址转换成相应的物理地址。
内存空间的扩充:利用虚拟存储技术或自动覆盖技术,从逻辑上扩充内存。
存储保护:保证各道作业在各自的存储空间内运行,互不干扰。
程序装入和链接
创建进程首先要将程序和数据装入内存。将用户源程序变为可在内存中执行的程序,通常需要以下几个步骤:
编译:由编译程序将用户源代码编译成若干个目标模块。
链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块。
装入:由装入程序将装入模块装入内存运行。
程序的链接有以下三种方式:
静态链接:在程序运行之前,先将各目标模块及它们所需的库函数链接成一个完整的可执行程序,以后不再拆开。
装入时动态链接:将用户源程序编译后所得到的一组目标模块,在装入内存时,釆用边装入边链接的链接方式。
运行时动态链接:对某些目标模块的链接,是在程序执行中需要该目标模块时,才对它进行的链接。其优点是便于修改和更新,便于实现对目标模块的共享。
模块在装入内存时,同样有以下三种方式:
绝对装入。在编译时,如果知道程序将驻留在内存的某个位置,编译程序将产生绝对地址的目标代码。绝对装入程序按照装入模块中的地址,将程序和数据装入内存。由于程序中的逻辑地址与实际内存地址完全相同,故不需对程序和数据的地址进行修改。
可重定位装入。在多道程序环境下,多个目标模块的起始地址通常都是从0开始,程序中的其他地址都是相对于起始地址的,此时应釆用可重定位装入方式。根据内存的当前情况,将装入模块装入到内存的适当位置。装入时对目标程序中指令和数据的修改过程称为重定位,地址变换通常是在装入时一次完成的,所以又称为静态重定位。静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。此外,作业一旦进入内存后,在整个运行期间不能在内存中移动,也不能再申请内存空间。
动态运行时装入,也称为动态重定位,程序在内存中如果发生移动,就需要釆用动态的装入方式。装入程序在把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址均为相对地址,这种方式需要一个重定位寄存器的支持。动态重定位的特点是可以将程序分配到不连续的存储区中;在程序运行之前可以只装入它的部分代码即可投入运行,然后在程序运行期间,根据需要动态申请分配内存;便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间。
在文章开始之前,先说下阅读本文后能学到的知识。
如果你已经掌握了这些知识,那么就不用继续阅读了,如果这些知识你都不熟悉或者不太清楚的话,那就继续阅读,从文章中来获取答案。
为什么会出现虚拟内存呢?这就要从最初的 *** 作系统来说起了,最初的 *** 作系统并没有现在那么完善,刚开始的时候,程序是直接装载到物理内存中的。这就导致了下面的一些问题:
先说问题1,为什么会导致程序编写困难呢?因为, *** 作系统是同时运行好多程序的,编写的程序是直接 *** 作物理内存的,编写的时候就要考虑,自己的程序 *** 作的内存地址,是否已经被其他程序占用了,如果被占用了的话,就要重新编写程序,重新安排程序的 *** 作地址。
再看问题2,因为是直接 *** 作物理内存,这就意味着一个程序可以 *** 作内存中的所有地址,如果有恶意程序修改了其他程序在用的地址中的数据,这就可能导致其他程序崩溃。
虚拟内存概念的出现就解决了上面的问题,虚拟内存的概念出现后,程序的编写就不再直接 *** 作物理内存了,对每个程序来说,它们就相当于拥有了所有的内存空间,可以随意 *** 作,就不用担心自己 *** 作的内存地址被其他程序占用的问题了。同时,因为程序 *** 作的是虚拟内存地址,这样就不会出现因为修改了其他应用程序内存地址中的数据而导致其他应用程序崩溃的问题了。
这时,你可能会问,CPU都是 *** 作物理内存的,这虚拟内存怎么和物理内存对应呢?问题很好,下文会给你答案。
这里有必要说下物理内存和虚拟内存的概念,可能有的读者分的不太清楚。
解读一下这张图,就是有1G虚拟内存是编写的应用程序 *** 作不到的,应用程序最多只能 *** 作3G的虚拟内存空间。
有计算机基础的人应该都知道,计算机的CPU *** 作的是物理内存的地址,而现在编写的程序 *** 作的都是虚拟内存地址,那么虚拟内存怎样和物理内存对应起来的呢?这就涉及到一些 *** 作系统的知识了,虚拟内存和物理内存都有分页的概念,一般一页是4096个字节, 现在的 *** 作系统虚拟地址和物理地址建立对应关系采用的是页映射的方式 。
假设我们的32位机器有16 KB的内存,每个页大小为 4096 字节,则共有4个页,
假设程序所有的指令和数据总和为32 KB,那么程序总共被分为8个页。我们将它们编号为P0~P7。很明显,16 KB的内存无法同时将32 KB的程序装入,那么我们将按照动态装入的原理来进行整个装入过程。如果程序刚开始执行时的入口地址在P0,这时装载管理器(我们假设装载过程由一个叫装载管理器的家伙来控制,就像覆盖管理器一样)发现程序的P0不在内存中,于是将内存F0分配给P0,并且将P0的内容装入F0;运行一段时间以后,程序需要用到P5,于是装载管理器将P5装入F1;就这样,当程序用到P3和P6的时候,它们分别被装入到了F2和F3,它们的映射关系如图所示。
可能上面的内容你还意犹未尽,那就再来简单的描述一下,Linux是怎样装载可执行程序的首先, *** 作系统是会为一个可执行程序分配一个进程的,然后装载相应的可执行文件并执行。当有虚拟内存存在的情况下,上面的过程就要做三件事:
首先是创建虚拟地址空间。创建一个虚拟空间实际上并不是创建空间而是创建映射函数所需要的相应的数据结构。
读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系。为什么要建立映射关系呢?因为, 当程序执行发生页错误时, *** 作系统将从物理内存中分配一个物理页,然后将该“缺页”从磁盘中读取到内存中,再设置缺页的虚拟页和物理页的映射关系 ,这样程序才得以正常运行。但是很明显的一点是,当 *** 作系统捕获到缺页错误时,它应知道程序当前所需要的页在可执行文件中的哪一个位置。这就是虚拟空间与可执行文件之间的映射关系。
再来看第3步,其实仔细思考第三步是会发现一些问题的,这里的可执行文件的入口地址是虚拟内存地址,那么就可能存在两个可执行程序的虚拟入口地址相同的问题,这个问题怎么解决呢?这时一个叫做“内存管理单元(Memory Management Unit)”简称“MMU”的硬件就诞生了,它的作用之一就是地址翻译,将虚拟地址翻译成物理地址,可以看下图,加深理解
简单总结一下这部分的内容,当 *** 作系统装载一个可执行程序时,会首先创建虚拟地址空间,这个地址空间实际上就是一个数据结构;然后建立可执行文件与虚拟地址的映射,映射的作用就是知道虚拟空间对应可执行文件的哪个位置;最后就是将CPU的指令寄存器设置成可执行文件的入口地址,开始执行程序,程序开始执行的时候是会到入口地址那里找数据或程序执行,如果入口地址没有程序或数据,就会产生缺页中断,然后将虚拟地址对应可执行文件中的部分装载到物理内存中,再将这块物理内存和虚拟内存建立映射。
本文主要讲解了虚拟内存有关的知识、简单的讲解了一下虚拟内存和物理内存之间的映射以及程序装载的过程,希望大家阅读后对虚拟内存能有更深的理解。
内核态,或者说CPU的特权模式,是CPU的一种工作状态,它影响CPU对不同指令的执行结果。 *** 作系统通过跟CPU配合,设置特权模式和用户模式,来防止应用程序进行越权的 *** 作
防止应用程序越权访问内存时使用了虚拟地址空间映射的技术,这是 *** 作系统软件配合硬件的MMU共同实现的。在用户模式下,应用程序访问的内存地址是虚拟内存地址,会映射到 *** 作系统指定的物理地址上。这个虚拟内存地址空间就是你说的用户空间。
内核态是个 *** 作系统概念,虽然对应到CPU的特权模式,但一般如果没有 *** 作系统,就不说内核态了,直接说运行在CPU的特权模式应该没毛病。
应用程序无法自由进入内核态,只能通过 *** 作系统提供的接口调用进入,或者在硬件中断到来时被动进入
应用程序通过 *** 作系统功能来使用硬件
以上就是关于关于sobel算子的图像边缘检测程序_利用sobel算子进行边缘提取全部的内容,包括:关于sobel算子的图像边缘检测程序_利用sobel算子进行边缘提取、内存管理的基本问题、你真的了解虚拟内存和物理内存吗等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)