程序编译虚拟地址
1. 如何将虚拟地址转化成pfn,即页帧号麻烦告诉我
用户程序中的虚拟地址,静态的是编译时就定好的,动态的(如malloc),是通过内核的页式内存管理在vma中定的,需要找到进程的task_struct中的页表然后一级级的翻译得到物理地址。
实际编译时定的地址叫做逻辑地址,这个逻辑地址是需要段式管理来翻译的,即段基址加段内偏移,由于linux中的这个段基址就是0,所以逻辑地址就直接对应了虚拟地址了。
这样得到物理地址以后,首先将十六进制的低三位与成0,这样做是得到页的物理地址,这里指4K页的情况,然后通过页的物理地址减去mem_map的第一个元素的地址就得到了此页在mem_map数组中的下标(此处注意指针相减不是指针表示的地址相减,而是两者之间指针所表示元素类型的个数),此下标即为pfn,知道了在数组中的下标就可以得到struct page结构体了,就可以知道page的所有情况了。
2. 我学C语言指针内存中的地址是什么意思
在每次我们声明一个变量时,系统会自动给变量在内存中分配一个地址,而指针如果只是声明它没有为它赋值的话,它就是个空指针,不指向任何的内存地址。 例如: int x =5,*p; p = &x ;
上面这句话, 声明了一个x 变量和一个指针p, 并且我们把变量x 的地址赋给了指针p,这样指针p 就指向了变量x的地址,*p 指的就是 它指向的地址上的值,也就是说 *p =5 ; 也就是说指针是用来存储地址的东西。
3. 在C语言程序中如何区分传递参数是虚拟地址还是物理地址
只能通过取值范围来判定。
一般情况下,如果是大于虚拟内存的地址,就是物理地址。
4. LinuxOS,Linux首先使用的是物理内存,然后使用虚拟内存。为什么编译程序的时候打印的是虚拟内存的地址
第一层理解
1. 每个进程都有自己独立的4G内存空间,各个进程的内存空间具有类似的结构
2. 一个新进程建立的时候,将会建立起自己的内存空间,此进程的数据,代码等从磁盘拷贝到自己的进程空间,哪些数据在哪里,都由进程控制表中的task_struct记录,task_struct中记录中一条链表,记录中内存空间的分配情况,哪些地址有数据,哪些地址无数据,哪些可读,哪些可写,都可以通过这个链表记录
3. 每个进程已经分配的内存空间,都与对应的磁盘空间映射
5. 既然计算机中程序和数据都有自己的物理地址,为何又要引入虚拟地址虚拟地址存在的必要性是什么
你可以认为这两者的区别就像机器语言和高级编程语言的区别,物理地址难记,不好管理,交给底层程序自己管理,但要进行读写必须对应物理地址。逻辑地址容易记,方便管理进行编程,降低了你对地址的管理难度。
6. 调试代码的时候显示的地址是物理地址还是虚拟地址
虚拟地址,是程序的地址,程序在操作系统中有入口地址,而程序中的地址则是入口地址的相对位置
。
物理地址就是,机器内主存的地址,包括RAM和ROM
虚拟地址就是,cpu支持的内存空间远远大于机器主存的大小,这些多出来的空间对于程序来说是可以用的,这个时候的所有地址都称为虚拟地址。
这个要学操作系统才能理解,推荐看
人民邮电出版社
7. 什么是虚拟地址
虚拟地址是Windows程序时运行在386保护模式下,这样程序访问存储器所使用的逻辑地址称为虚拟地址,与实地址模式下的分段地址类似,虚拟地址也可以写为“段:偏移量”的形式,这里的段是指段选择器。
8. C++,输出变量的地址,那个地址是程序虚拟地址空间的地址还是实际的物理地址
源代码在编译时虚拟地址是已经确定好的,而程序中打印的地址是虚拟地址,所以两次打印的是一样的!
9. 请问下虚拟地址的问题
那个账号提交有问题,换个账号回答你。
首先,虚拟地址和逻辑地址是一样的概念。
linux分段的时候把不同进程映射到不同的线性地址,是在linux 0.11内核代码中出现的。之所以这样是因为,0.11版本虽然开启了分页机制,但是所有进程共享了同一个页目录,所以进程们只能分配其中一段使用。这时候每个进程的线性地址空间没有那么大(没有4GB)。
后来linux内核为了增大单个进程的线性地址空间,就不再共享页目录,也就是每个进程有独立的页目录,此时进程的段地址基址就可以设置为0,而不会再相互干涉。
每个进程基址都从0开始,并且都拥有4GB的线性地址空间,这就相当于没有使用分段机制,实际上分段和分页都采用了。
10. 操作系统课程设计物理地址和虚拟地址的联系及区别
CPU通过地址来访问内存中的单元,地址有虚拟地址和物理地址之分,如果CPU没有MMU(Memory Management Unit,内存管理单元),或者有MMU但没有启用,CPU核在取指令或访问内存时发出的地址将直接传到CPU芯片的外部地址引脚上,直接被内存芯片(以下称为物理内存,以便与虚拟内存区分)接收,这称为物理地址(Physical Address,以下简称PA),如下图所示。
MMU将虚拟地址映射到物理地址是以页(Page)为单位的,对于32位CPU通常一页为4K。例如,虚拟地址0xb700 1000~0xb700 1fff是一个页,可能被MMU映射到物理地址0x2000~0x2fff,物理内存中的一个物理页面也称为一个页框(Page Frame)。
物理地址(physical address)
用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应。
——这个概念应该是这几个概念中最好理解的一个,但是值得一提的是,虽然可以直接把物理地址理解成插在机器上那根内存本身,把内存看成一个从0字节一直到最大空量逐字节的编号的大数组,然后把这个数组叫做物理地址,但是事实上,这只是一个硬件提供给软件的抽像,内存的寻址方式并不是这样。所以,说它是“与地址总线相对应”,是更贴切一些,不过抛开对物理内存寻址方式的考虑,直接把物理地址与物理的内存一一对应,也是可以接受的。也许错误的理解更利于形而上的抽像。
虚拟内存(virtual memory)
这是对整个内存(不要与机器上插那条对上号)的抽像描述。它是相对于物理内存来讲的,可以直接理解成“不直实的”,“假的”内存,例如,一个0x08000000内存地址,它并不对就物理地址上那个大数组中0x08000000 - 1那个地址元素;
之所以是这样,是因为现代操作系统都提供了一种内存管理的抽像,即虚拟内存(virtual memory)。进程使用虚拟内存中的地址,由操作系统协助相关硬件,把它“转换”成真正的物理地址。这个“转换”,是所有问题讨论的关键。
有了这样的抽像,一个程序,就可以使用比真实物理地址大得多的地址空间。(拆东墙,补西墙,银行也是这样子做的),甚至多个进程可以使用相同的地址。不奇怪,因为转换后的物理地址并非相同的。
——可以把连接后的程序反编译看一下,发现连接器已经为程序分配了一个地址,例如,要调用某个函数A,代码不是call A,而是call 0x0811111111 ,也就是说,函数A的地址已经被定下来了。没有这样的“转换”,没有虚拟地址的概念,这样做是根本行不通的。
打住了,这个问题再说下去,就收不住了。
逻辑地址(logical address)
Intel为了兼容,将远古时代的段式内存管理方式保留了下来。逻辑地址指的是机器语言指令中,用来指定一个操作数或者是一条指令的地址。以上例,我们说的连接器为A分配的0x08111111这个地址就是逻辑地址。
——不过不好意思,这样说,好像又违背了Intel中段式管理中,对逻辑地址要求,“一个逻辑地址,是由一个段标识符加上一个指定段内相对地址的偏移量,表示为 [段标识符:段内偏移量],也就是说,上例中那个0x08111111,应该表示为[A的代码段标识符: 0x08111111],这样,才完整一些”
线性地址(linear address)或也叫虚拟地址(virtual address)
跟逻辑地址类似,它也是一个不真实的地址,如果逻辑地址是对应的硬件平台段式管理转换前地址的话,那么线性地址则对应了硬件页式内存的转换前地址。